Gaurav Singhal Gaurav is a data scientist with a strong background in computer science and mathematics. As a developer, he works with Python, Java, Django, HTML, Struts, Hibernate, Vaadin, web scraping, Angular, and React.

The MUI grid system

6 min read 1910

The MUI grid system

Editor’s note: This post was updated 13 December 2021 to reflect breaking changes from MUI’s v5 release, make clearer the difference between Google’s Material Design and the React library MUI, and update the code snippets accordingly.

What is the difference between Material Design and MUI?

Material Design is a popular design system developed by Google in 2014. It is a visual language that synthesizes the classic principles of good design with the innovation of technology and science.

Google and many other tech companies use Material Design extensively across their brand and products. In 2021, Google revamped its design system, making it more flexible for designers to create custom themes.

The MUI library is a React library that implements Google’s Material Design and its grid system. Widely used in Android app development, it defines a set of principles and guidelines for designing UI components. The creators of this technology shortened the project’s name from Material-UI to MUI back in September 2021. They did this to clarify developers that this project was never affiliated with Google.

MUI comes with prebuilt UI components, including buttons, navbars, navigation drawers, and, most importantly, the grid system. To facilitate new features, MUI also updated its libraries (v5). Other than updated design, the new version also includes performance optimization and enhanced theming options.

In this guide, we’ll be exploring how to use it to build applications with React. First, we’ll dig into the grid system, its features and limitations, and React implementation.

Material Design’s grid system

A grid system defines a set of measurements to place elements or components on the page based on successive columns and rows. The grid system in Material Design is visually balanced. It adapts to screen sizes and orientation, which ensures a consistent layout across pages.

The grid system consists of three components:

  1. Columns — Elements on the page are placed within columns, which are defined by percentages rather than fixed values so that the elements can flexibly adapt to any screen size
  2. Gutters — The spaces between the columns are defined by a fixed value at each breakpoint to better adapt the screen size
  3. Margins — The spaces between the left and right sides of the screen are defined by a fixed value similar to gutters, at each breakpoint

Implementation in React with the MUI library

The MUI library provides React components that implement Google’s Material Design.

Installation

Run the following command to install the following dependencies in your project.

We made a custom demo for .
No really. Click here to check it out.

npm install @mui/material @emotion/react @emotion/styled

Material Design uses Roboto as the default font, so don’t forget to add it as well.

<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>

Basic use

All the components are isolated, self-supporting, and only inject styles that they need to present. Below is a quick example to get things going.

import * as React from "react";
//import the Button component from MUI
import Button from "@mui/material/Button";
export default function App() {
  return (
    //Draw a simple button
    <Button variant="contained" color="primary">
      MUI Demo
    </Button>
  );
}

A demo button built using MUI

The grid component

Material Design’s grid system is implemented in MUI using the <Grid /> component. Under the hood, the <Grid /> component uses Flexbox properties for greater flexibility.

There are two types of grid components: containers and items. To make the layout fluid and adaptive to screen sizes, the item widths are set in percentages. Padding creates spacing between individual items. Finally, there are five types of grid breakpoints: xs, sm, md, lg, and xl.

Import the Grid component

To import the <Grid /> component into the JavaScript file, use the following line.

import Grid from '@mui/material/Grid';

Containers and items

The container prop gives the <Grid /> component the CSS properties of a flex container, and the item prop gives the CSS properties of a flex item.

The items must be wrapped in a container, as shown below.

<Grid
  container
  // ...this parent component will be a flex-box container
>
  <Grid
    item
    // ... this child component will be a flex item for the parent Grid
  >
    <Paper></Paper> {/* A simple flex item */}
  </Grid>
</Grid>

Features

Let’s look at the various props you can provide to the container and item to build a flexible layout.

Spacing

You can apply the spacing prop to the grid container to create spaces between individual grid items. In the following example, we interactively change the spacing prop value by passing the value through a set of radio button components.

import * as React from "react";
import Grid from "@mui/material/Grid";
import FormLabel from "@mui/material/FormLabel";
import FormControlLabel from "@mui/material/FormControlLabel";
import RadioGroup from "@mui/material/RadioGroup";
import Radio from "@mui/material/Radio";
import Paper from "@mui/material/Paper";

//create our style
const styles = {
  paper: {
    height: 140,
    width: 100,
    backgroundColor: "black"
  }
};
export default function SpacingGridDemo() {
  //create our spacing variable. Default value will be 2
  const [spacing, setSpacing] = React.useState(2);
  //when executed, change the value of spacing Hook to chosen value
  const handleChange = (event) => {
    setSpacing(Number(event.target.value));
  };
  return (
    <div>
      <div>
        {/*This container will be aligned in the center */}
        {/* Spacing will vary depending on user choice.*/}
        <Grid container justify="center" spacing={spacing}>
          {/*Render 3 empty black boxes as items of this container*/}
          {[0, 1, 2].map((value) => (
            <Grid key={value} item>
              <Paper style={styles.paper} />
            </Grid>
          ))}
        </Grid>
      </div>
      <div>
        <Paper>
          <div>
            {/* Show user's chosen spacing value*/}
            <FormLabel>{spacing}</FormLabel>
            <RadioGroup
              name="spacing"
              aria-label="spacing"
              value={spacing.toString()}
              onChange={handleChange}
              row
            >
              {/*Render multiple spacing values in a form */}
              {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((value) => (
                <FormControlLabel
                  key={value}
                  value={value.toString()}
                  control={<Radio />}
                  label={value.toString()}
                />
              ))}
            </RadioGroup>
          </div>
        </Paper>
      </div>
    </div>
  );
}

Change the spacing dynamically by passing the spacing values through the radio button component

Fluid grids

We can create layouts for different screen sizes by using the breakpoint props (xs, sm, md, lg, xl) on the grid items. Fluid grids can scale the grid items and resize content within them.

import * as React from "react";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";
//create our styles
const classes = {
  root: {
    flexGrow: 1
  },
  paper: {
    padding: 20,
    textAlign: "center",
    color: "blue",
    fontFamily: "Roboto"
  }
};
export default function BreakpointGridDemo() {
  return (
    <div style={classes.root}>
      <Grid container spacing={3}>
        {/*Create items with different breakpoints */}
        {/*For example,This item will be 12 units wide on extra small screens */}
        <Grid item xs={12}>
          <Paper style={classes.paper}>xs=12</Paper>
        </Grid>
        {/*This item will be 12 units on extra small screens */}
        {/*But will be 6 units on small screens */}
        <Grid item xs={12} sm={6}>
          <Paper style={classes.paper}>xs=12 sm=6</Paper>
        </Grid>
        <Grid item xs={12} sm={6}>
          <Paper style={classes.paper}>xs=12 sm=6</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper style={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper style={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper style={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper style={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
      </Grid>
    </div>
  );
}

Using fluid grids to scale content for different screen sizes

Auto-layout

The auto-layout feature allows the grid items to auto-resize and occupies the available space without having to specify the width of the item. If you set width on one of the items, the child items would automatically resize and share the available space.

In the following example, you can see that the items around the xs={9} item auto-resize, resulting in a perfect layout.

const classes = {
  root: {
    flexGrow: 1
  },
  paper: {
    padding: 20,
    textAlign: "center",
    backgroundColor: "black",
    color: "white"
  }
};
export default function AutoGridDemo() {
  return (
    <div style={classes.root}>
      <Grid container spacing={2}>
        {/*They all will have default widths */}
        <Grid item xs>
          <Paper style={classes.paper}>xs</Paper>
        </Grid>
        <Grid item xs>
          <Paper style={classes.paper}>xs</Paper>
        </Grid>
        <Grid item xs>
          <Paper style={classes.paper}>xs</Paper>
        </Grid>
      </Grid>
      <Grid container spacing={2}>
        <Grid item xs>
          <Paper style={classes.paper}>xs</Paper>
        </Grid>
        <Grid item xs>
          <Paper style={classes.paper}>xs</Paper>
        </Grid>
        {/*However, this component will have 9 units of space */}
        <Grid item xs={9}>
          <Paper style={classes.paper}>xs=9</Paper>
        </Grid>
      </Grid>
    </div>
  );
}

Using the auto-layout feature to achieve a perfect layout every time

Nested grids

We can use grids within each other. In the demo below, the container and item props are combined so the <Grid /> component can act like both a container and an item. This allows us to have another set of the grid inside the grid item. In this case, it’s the <InnerGrid /> component.

import * as React from "react";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";

const classes = {
  root: {
    flexGrow: 1
  },
  paper: {
    padding: 20,
    textAlign: "center",
    color: "blue"
  }
};
//the InnerGrid component will be a collection of multiple Grid items
function InnerGrid() {
  return (
    <>
      <Grid item xs={4}>
        <Paper style={classes.paper}>item</Paper>
      </Grid>
      <Grid item xs={4}>
        <Paper style={classes.paper}>item</Paper>
      </Grid>
      <Grid item xs={4}>
        <Paper style={classes.paper}>item</Paper>
      </Grid>
    </>
  );
}
export default function NestedGridDemo() {
  return (
    <div style={classes.root}>
      <Grid container spacing={1}>
        <Grid container item xs={12} spacing={3}>
          {/*Render the InnerGrid as a child item */}
          <InnerGrid />
        </Grid>
        <Grid container item xs={12} spacing={3}>
          <InnerGrid />
        </Grid>
        <Grid container item xs={12} spacing={3}>
          <InnerGrid />
        </Grid>
      </Grid>
    </div>
  );
}

Nested grids in MUI

Limitations of MUI

Negative margin

MUI uses a negative margin to implement spaces between grid items. When the negative margin goes beyond the <body>, a horizontal scroll appears.

To fix this, the MUI documentation suggests:

  1. Not using the spacing feature and implementing it in userspace spacing={0} (default)
  2. When applying a background color, first apply the display:flex style to the parent

white-space no-wrap

By default, the flex items have the min-width property set to auto. This causes a conflict in positioning when the child is using white-space: nowrap; property.

To fix this problem, we need to set the min-width: 0 or zeroMinWidth property on the grid item like so:

<Grid item xs zeroMinWidth>
  <Typography noWrap>
  ...

column and column-reverse

Some of the grid features are not supported for direction: column and direction: column-reverse. The breakpoints are focused on controlling the width and do not have a similar effects on height within column containers.

Conclusion

Despite the handful of drawbacks described above, MUI enables you to create innovative, responsive layouts. Hopefully, this guide will help you take full advantage of the numerous features we discussed. They’ll come in handy at some point or another when you’re working with the Material Design system.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Gaurav Singhal Gaurav is a data scientist with a strong background in computer science and mathematics. As a developer, he works with Python, Java, Django, HTML, Struts, Hibernate, Vaadin, web scraping, Angular, and React.

4 Replies to “The MUI grid system”

  1. Your mistakenly confusing Material Design, the UI/ux design patterns created by Google and Material UI a react library that implements Material Design.

  2. Hi,

    Yes you are right, Material-UI is an open source react library and is not developed by Google. I got caught up with the symmetry and similarities of terms. I have made the required changes.
    I hope you like the article.

    Best Regards,
    Gaurav Singhal

  3. Thanks for the article, really helpful for me when learning about this!

    Hope you don’t mind me posting two super minor bugs in case other readers copy/paste your code blocks like I did when I was learning:

    * In the ‘Spacing’ section, I think you meant to write {spacing}, so spacing variable value is printed to the screen

    * In the ‘Fluid grids’ section, you use the variable ‘theme’ which is undefined. I think you’ve done the standard ‘makeStyles’ but are missing a bit of code for that:


    import { makeStyles } from ‘@material-ui/core/styles’;

    const useStyles = makeStyles((theme) => ({
    root: {
    flexGrow: 1
    },
    paper: {
    padding: 20,
    textAlign: “center”,
    color: theme.palette.text.secondary,
    fontFamily: “Roboto”
    }
    }));

    export default function BreakpointGridDemo() {
    const classes = useStyles();

    Thanks again!

Leave a Reply