The Ultimate Guide to Material UI Theme Breakpoints

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:

MUI Theme Breakpoint Tutorial
MUI Theme Breakpoint Tutorial

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).

MUI theme.breakpoints.up example
MUI theme.breakpoints.up example

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).

MUI theme.breakpoints.down example
MUI theme.breakpoints.down example

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.

MUI theme.breakpoints.between Example
MUI theme.breakpoints.between Example

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:

MUI theme.breakpoints.only Example
MUI theme.breakpoints.only Example

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:

MUI theme.breakpoints.not Example
MUI theme.breakpoints.not Example

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>
    </>
  );
}
Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.