The MUI Theme can be customized with new values for existing breakpoints, and it can even have new breakpoints added (i.e. bg: 1000
). In this tutorial we will customize theme breakpoints and show an example of every breakpoint function being used (i.e. theme.breakpoints.up and theme.breakpoints.down).
Here’s a screenshot of what we will create. It can have different background color depending on screen size:

Finally, I will discuss some issues that I found, such as import { ThemeProvider } from "@mui/styles";
not working.
Full code for this tutorial is in the Resources section.
How to Create Custom Breakpoints and Breakpoint Values in MUI Theme
We can easily create a custom breakpoint by adding a new key:value pair to the theme.breakpoints object. If we customize the theme.breakpoints object, we need to restate existing theme key:value pairs or give keys new values.
Take a look at the example code below where I added a new breakpoint of bg: 900
.
import { createTheme } from "@mui/material/styles";
declare module '@mui/material/styles' {
interface BreakpointOverrides {
xs: true;
sm: true;
md: true;
bg: true;
lg: true;
xl: false;
}
}
const BreakPointTheme = createTheme({
breakpoints: {
values: {
xs: 0,
sm: 300,
md: 600,
bg: 900,
lg: 1200
}
}
});
export { BreakPointTheme };
I use TypeScript in my projects. In order to add the new breakpoint, I needed to create interface BreakpointOverrides in '@mui/material/styles'
module.
I then imported this theme in my BreakPointTextField component and passed it via a ThemeProvider. Here’s a sample of the code:
<ThemeProvider theme={BreakPointTheme}>
<TextField
defaultValue="bg"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.not('md')]: {
backgroundColor: 'green',
},
width: { xs: 200, sm: 300, md: 400, bg: 500 }
}}
/>
<TextField
defaultValue="sm"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.between('sm', 'md')]: {
backgroundColor: 'orange',
},
width: { xs: 200, sm: 300 }
}}
/>
</ThemeProvider>
Notice how the width in the first TextField makes use of the bg
breakpoint. Interestingly, I found that the width had to be the last value in the sx
prop for the custom bg
breakpoint or else it ‘disappeared’ when I added additional styling.
Also, I initially used import { ThemeProvider } from "@mui/styles";
but it simply didn’t work. There were no visible issues, TypeScript threw no errors, but it simply didn’t work until I imported from "@mui/material/styles"
.
In the screenshot in the introduction, you can see an example of each breakpoint being used to set a different width on each TextField.
How to Use theme.breakpoints.up
The theme comes with several functions for applying styling above, below, at, or not on certain breakpoints. The up
function is the most used according to my keyword research.
Here’s example code of how it’s used:
<TextField
sx={{
[BreakPointTheme.breakpoints.up('bg')]: {
backgroundColor: 'red',
}
}}
</TextField>
In this case, red background color will be applied any time the screensize is equal to or wider than 900px, which is my custom bg breakpoint. It will even be applied after the lg
breakpoint is passed (1200px).

We see in the screenshot above how this is rendering and how the selector looks in dev tools styles.
How to Use theme.breakpoints.down
The down
function is the second most commonly used breakpoint function according to my research. Here’s an example of it being used:
<TextField
defaultValue="xs"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.down('sm')]: {
backgroundColor: 'primary.main',
},
width: { xs: 200 } }}
/>
With this code, the primary.main
color will be applied to background any time the screen is smaller than 300 px (my custom sm
breakpoint value in my theme).

The down
function is applied to the top TextField in the screenshot above.
How to Use theme.breakpoints.between
The between
function only applies a styling between two breakpoint values, inclusive of the lower and exclusive of the upper. Here’s code from my demo:
<TextField
defaultValue="sm"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.between('sm', 'bg')]: {
backgroundColor: 'orange',
},
width: { xs: 200, sm: 300 }
}}
/>
In the screenshot below, between
is used on the second TextField.

We can see from the dev tools styling section that orange background color is only applied between 300px and 899.95px.
How to Use theme.breakpoints.only
The only
function applies a value only on one breakpoint. This is different from up
, which applies a value starting at a breakpoint and also to all larger breakpoints. It is different from down
, which applies to a specified breakpoint and to all smaller breakpoints.
Here is example code:
<TextField
defaultValue="md"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.only('md')]: {
backgroundColor: 'pink',
},
width: { xs: 200, sm: 300, md: 400 } }}
/>
The third TextField in the screenshot has the only
breakpoint function applied:

Notice how the pink background is only applied between 600px and 899.95px. This is like using the between
function only from md
to bg
.
How to Use theme.breakpoints.not
The not
function is my favorite of the breakpoint functions. It applies a styling except when a certain breakpoint is entered. Here’s example code:
<TextField
defaultValue="bg"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.not('md')]: {
backgroundColor: 'green',
},
width: { xs: 200, sm: 300, md: 400, bg: 500 } }}
/>
Any time the screen is not between 600px and 900px then the background of the fourth TextField will be green:

Take a look at the dev tools styling section. The syntax for applying the media query is pretty complex. It uses “not min and max” logic to accomplish the styling.
Resources
Here’s a link to the MUI Breakpoint Documentation.
Full code for this tutorial:
import { TextField } from "@mui/material";
import { ThemeProvider, Theme } from "@mui/material/styles";
import { createTheme } from "@mui/material/styles";
declare module '@mui/material/styles' {
interface BreakpointOverrides {
xs: true;
sm: true;
md: true;
bg: true;
lg: true;
xl: false;
}
}
const BreakPointTheme = createTheme({
breakpoints: {
values: {
xs: 0,
sm: 300,
md: 600,
bg: 900,
lg: 1200
}
}
});
export { BreakPointTheme };
const tfStyles = (BreakPointTheme: Theme) => ({
backgroundColor: "yellow",
// [BreakPointTheme.breakpoints.down('sm')]: {
// backgroundColor: 'primary.main',
// },
// [BreakPointTheme.breakpoints.between('sm', 'md')]: {
// backgroundColor: 'orange',
// },
// [BreakPointTheme.breakpoints.only('md')]: {
// backgroundColor: 'pink',
// },
// [BreakPointTheme.breakpoints.not('md')]: {
// backgroundColor: 'green',
// },
// [BreakPointTheme.breakpoints.up('bg')]: {
// backgroundColor: 'red',
// }
});
export default function BreakPointTextField() {
return (
<>
<ThemeProvider theme={BreakPointTheme}>
<TextField
defaultValue="xs"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.down('sm')]: {
backgroundColor: 'primary.main',
},
width: { xs: 200 } }}
/>
<TextField
defaultValue="sm"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.between('sm', 'md')]: {
backgroundColor: 'orange',
},
width: { xs: 200, sm: 300 }
}}
/>
<TextField
defaultValue="md"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.only('md')]: {
backgroundColor: 'pink',
},
width: { xs: 200, sm: 300, md: 400 } }}
/>
<TextField
defaultValue="bg"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.not('md')]: {
backgroundColor: 'green',
},
width: { xs: 200, sm: 300, md: 400, bg: 500 } }}
/>
<TextField
defaultValue="lg"
variant="filled"
sx={{
...tfStyles(BreakPointTheme),
[BreakPointTheme.breakpoints.up('bg')]: {
backgroundColor: 'red',
},
width: { xs: 200, sm: 300, md: 400, bg: 500, lg: 600 } }}
/>
</ThemeProvider>
</>
);
}