Using Breakpoints in MaterialUI
Published: 2021-09-03 16:52:41

![MUI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x99qusomdtlnzm8zizen.png)

#What are breakpoints?

Have you ever been styling a webpage, just to notice that your text cuts off the screen when the browser window shrinks? Or that the webpage is a mess and hard to use from a phone's browser? Well, many other developers noticed the same thing and came up with the concept of breakpoints.

Breakpoints are pixel values for a specific webpage. Used in software development, they help us create more responsive webpages. So how exactly do they work? Well, they're generally used to provide **CSS conditions** for elements. We can say to a css element: "Style my element this way, but once the webpage pixels pass a certain threshold, change to styling this way." By doing this, we can make our webpages more responsive, meaning they respond and update according to the size of our browser. 

As an example, we can set up some conditional CSS to shrink the font of some given text and apply word wrap once the window shrinks to a certain level. Now, the text wont cut off the screen, but will instead wrap and be more easily readable.

#Breakpoints in Material UI

So we now know what breakpoints are, but how are they used in Material UI? Well, Material UI actually does a lot of the hard stuff for us. Firstly, they set up **default breakpoint values** as part of their default theme. These values, being extra small (xs), small (sm), medium (md), large (lg), and extra large (xl), all hold a unique pixel value that corresponds to a specific window size like so:

| Size          | Variable Name | Value |
| ------------- |:-------------:|:-----:|
| extra small   | xs            | `0px` |
| small         | sm            |`600px`|
| medium        | md            |`960px`|
| large         | lg            |`1280px`|
| extra large   | xl            |`1920px`|

Material UI uses breakpoints a lot, specifically with components like Grids. If you've used a grid before, you know that the items take in props that correspond to a given breakpoints variable name and a number out of 12, like `xs={12} sm={6}`. These props are telling the grid component that when the window is above breakpoint small, or `600px`, the grid item takes up half of a row (since rows are 12 columns in MUI). Once the window shrinks to above the extra small breakpoint but below the small one, or `0px-599px`, the grid item will take up an entire row.

Material UI's default breakpoint values are also changeable when creating a custom Material UI theme. Look at the [default theme documentation here](https://material-ui.com/customization/default-theme/#default-theme) to see exactly where you need to override. 


#Material UI Media Queries 

Now we know how Material UI characterizes breakpoints and uses them in their components, but what about that conditional CSS that we were talking about earlier? Well, Material UI also have some **custom media queries** that can be used to render conditional css. Generally used inside of a makeStyles function, it can responsively render different CSS based on breakpoint values.

Lets start by setting up a basic makeStyles function for some text:

```javascript
import { makeStyles, useTheme, Typography } from '@material-ui/core'

const useStyles = makeStyles(theme ({
  textExample: {
    fontSize: '4rem',
    texAlign: 'center'
  }
})

function StartingPage() {
  const theme = useTheme();
  const classes = useStyles(theme);

  return (
    <Typography
      className={classes.textExample}
    >
      This is an Example
    </Typography>
  );

}
```

This code will render a line of text in the center of our page and give it a font size of `4rem`. Here's how it looks:

![Starting Img](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nq0c0kbuiq0m43bzl2aw.png)

Now, let's start adding some conditional CSS!

##Theme.breakpoints.up

`theme.breakpoints.up('variable')` is a Material UI helper that targets a screen size **greater than and equal** to a given variable. So `theme.breakpoints.up('md')` targets the screen size from when it is `960px` or more. 

We can use it in our makeStyles function to conditionally render css like shown:

```javascript
import { makeStyles, useTheme, Typography } from '@material-ui/core'

const useStyles = makeStyles(theme ({
  textExample: {
    fontSize: '4rem',
    texAlign: 'center',
    [theme.breakpoints.up('md')]: {
       color: 'red'
    }
  }
})

function StartingPage() {
  const theme = useTheme();
  const classes = useStyles(theme);

  return (
    <Typography
      className={classes.textExample}
    >
      This is an Example
    </Typography>
  );

}
```

This piece of conditional css will change the color of our text to red if the window size is medium or larger. Lets test it out:

**Small Window**
![small window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r48rz9bvq2gy2rez7ipx.png)

**Medium Window**
![medium window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdrqdhdwiq290mrb0pby.png)

##Theme.breakpoints.down

As you could probably guess by the name, this helper does the exact opposite of `theme.breakpoints.up`. It targets a screen size **less than and equal to** a given variable. So using `theme.breakpoints.down('sm')` targets a screen size that is less than and including `600px`.

Lets add it to our styling:

```javascript
import { makeStyles, useTheme, Typography } from '@material-ui/core'

const useStyles = makeStyles(theme ({
  textExample: {
    fontSize: '4rem',
    texAlign: 'center',
    [theme.breakpoints.up('md')]: {
       color: 'red'
    },
    [theme.breakpoints.down('sm')]: {
      fontSize: '1rem'
    }
  }
})

function StartingPage() {
  const theme = useTheme();
  const classes = useStyles(theme);

  return (
    <Typography
      className={classes.textExample}
    >
      This is an Example
    </Typography>
  );

}
```

This code is going to change our font size from `4rem` to `1rem` if the window is smaller than or equal to `600px`. Lets test it out!

**Small Window**
![small window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6tovzszaisa7hvqqbq9.png)

**Medium Window**
![medium window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dedrwbkkgmr5o20lneql.png)

##Theme.breakpoints.between

Again, this helper is a lot like the previous two. It takes in **two variables** and targets the screen starting at the first variable and up to, and including, the second variable. So `theme.breakpoints.between('sm', 'md')` is going to target the screen from `600px` to `960px`.

Lets remove our previous breakpoints and add this one to our code:

```javascript
import { makeStyles, useTheme, Typography } from '@material-ui/core'

const useStyles = makeStyles(theme ({
  textExample: {
    fontSize: '4rem',
    [theme.breakpoints.between('sm', 'md')]: {
       color: 'blue'
    }
  }
})

function StartingPage() {
  const theme = useTheme();
  const classes = useStyles(theme);

  return (
    <Typography
      className={classes.textExample}
    >
      This is an Example
    </Typography>
  );

}
```

Now, our text will change from black to blue when our window is between `600px` and `960px`. Lets test it out:

**Extra Small Window**
![extra small window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x806386s7z7cvmgz00pu.png)

**Small Window**
![small window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6qa32m3udhnmxjbn24de.png)

**Medium Window**
![medium window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz3cth89g9v0tpc6vg1a.png)

**Large Window**
![large window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bx8o1lwaj92yf6w8lgls.png)

##Theme.breakpoints.only

And once again, this helper has a pretty self explanatory name. The `theme.breakpoints.only` helper **only** targets the screen when it is within the boundaries of a given variable. So `theme.breakpoints.only('sm')` **only** targets the screen when it is greater than `600px` and less than `960px` (which is the threshold for 'md').

Let's change our code around to incorporate it!

```javascript
import { makeStyles, useTheme, Typography } from '@material-ui/core'

const useStyles = makeStyles(theme ({
  textExample: {
    fontSize: '4rem',
    [theme.breakpoints.only('sm')]: {
       color: 'blue'
    }
  }
})

function StartingPage() {
  const theme = useTheme();
  const classes = useStyles(theme);

  return (
    <Typography
      className={classes.textExample}
    >
      This is an Example
    </Typography>
  );

}
```

This code is now going to change our text color to blue **only** when it is greater than `600px` and less than `960px`. Let's test it out!

**Extra Small Window**
![extra small window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owmyusei7rihx2kmdoh5.png)

**Small Window**
![small window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y98dcriduk6w9bbt6z9e.png)

**Medium Window**
![medium window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrhtcy4w4z0r4c25r0xa.png)

##useMediaQuery Hook

Finally, we have the useMediaQuery hook. This hook takes in one of our previously defined helpers and returns a boolean value. If the window is currently targeting the screen, the hook returns `true`, and if it isn't the hook returns `false`. An example of this hook goes like this: `useMediaQuery(theme.breakpoints.only('sm')`. If the window size is between `600px` and `959px`, the hook returns `true`, otherwise it returns `false`. 

So why is this useful? Well, using this hook, we now have a way to responsively render entire components. Say you wanted to display a table with a bunch of transaction information. The table has columns for `name`, `description`, `date`, and `amount`. Now, when you have a large screen thats all fine, but when the screen size shrinks, the information on the table will start to get messed up. Either it will cut off the screen or it will wrap poorly and be ugly to look at and hard to read. Thats where our useMediaQuery hook comes in. We don't really *need* to see the description of the transaction when the table starts to shrink, so why don't we responsively render that so it disappears when our screen shrinks below `960px`. By using the `theme.breakpoints.up('sm')` helper with useMediaQuery, we can have it return `true` when the window is larger than or equal to `960px` and false when it's smaller. We can then use this to conditionally render our descriptions, like so:

```javascript
import {
    useTheme,
    useMediaQuery,
    Paper,
    Table,
    TableContainer,
    TableHead,
    TableBody,
    TableRow,
    TableCell
} from '@material-ui/core'

function StartingPage() {
  const theme = useTheme();
  const isSmallOrLess = 
  useMediaQuery(theme.breakpoints.up('md'));

    const rows = [
        { name: 'Banana', description: 'Bought at the target 
          on sale for half off', amount: '2.25', date: 
          '7/07/21' },
        { name: 'Apple', description: 'Bought fresh from the 
          farmers market!', amount: '1.75', date: '8/23/21' 
          },
        { name: 'Orange', description: 'Picked right off the 
          tree! Free fruit!', amount: '0.00', date: 
          '9/02/21' },
        { name: 'Mango', description: 'Bought at the grocery 
          store. Why are mangos so expensive!?!', amount: 
          '8.25', date: '9/12/21' }
    ];

    return (
        <TableContainer component={Paper}>
            <Table>
                <TableHead>
                    <TableRow>
                        <TableCell>Name</TableCell>
                        {   isSmallOrLess ?
                            <TableCell>Description</TableCell>
                            :
                            null
                        }
                        <TableCell>Amount</TableCell>
                        <TableCell>Date</TableCell>
                    </TableRow>
                </TableHead>
                <TableBody>
                    {rows.map(row => (
                        <TableRow>
                            <TableCell>{row.name}</TableCell>
                            {isSmallOrLess ?
                                <TableCell>{row.description}</TableCell>
                                :
                                null
                            }
                            <TableCell>{row.amount}</TableCell>
                            <TableCell>{row.date}</TableCell>
                        </TableRow>
                    ))}
                </TableBody>
            </Table>
        </TableContainer>
    );
}
```

This code is building out a basic table and loading it with four rows of data. Although it may look overwhelming, the important places to pay attention to are where we are conditionally rendering our component. Up near the top we are using our useMediaQuery hook and storing that value in a constant called `isSmallOrLess`. That constant is then being used in a ternary expression when rendering the description parts of our header and body. What this will do is render the component if `isSmallOrLess` is true, otherwise it will return null and not render anything.

Let's try it out!

**Small Window**
![small window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27np3b71d59n1gzu9xug.png)

**Medium Window**
![medium window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zxfb4hblpko2jsxom5u.png)

#Conclusion

Breakpoints are a great way to make our webpages more responsive and user-friendly, but like any css, it can be a hassle to set up. Material UI, once again, makes everyone's lives a little easier by providing a bunch of custom breakpoints, helpers for conditionally rendering css, and a hook for conditionally rendering components.

If you would like to learn more about using breakpoints in Material UI, the documentation page [here](https://material-ui.com/customization/breakpoints/#breakpoints) is a great source of information. There is also a useful stack overflow page [here](https://stackoverflow.com/questions/52484812/reactjs-material-ui-breakpoints) that gives a clear and concise overview on the subject.

Good luck and happy coding!