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.

Guide to the MUI grid system

8 min read 2422

MUI Grid System Getting Started

Editor’s note: This post was last updated 16 November 2022 to include information about MUI Grid v2.

In this article, we’ll explore building an application with React using MUI. First, we’ll learn about the MUI grid system, its features and limitations, and implementing it in React. Let’s get started!

Material Design vs. 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 innovations in 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.

MUI is a React library that implements Google’s Material Design and its grid system. Widely used in Android app development, MUI 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 in September 2021, clarifying that the project was never affiliated with Google.

MUI comes with prebuilt UI components, including buttons, navbars, navigation drawers, and, most importantly, the grid system. MUI v5 offered new features, an updated design, performance optimization, and enhanced theming options.

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, ensuring a consistent layout across pages.

The grid system consists of three components:

  1. Columns: Elements on the page are placed in 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

Implementing Material Design in React with MUI

The MUI library provides React components that implement Google’s Material Design. Let’s explore implementing Material Design in a React app using MUI.

Installation

Run the command below to install the required dependencies in your project:

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"
/>

Alternately, you can omit the snippet above and add the following imports to the entry point of your React app instead, which should normally be the index.js file:

import "@fontsource/roboto/300.css";
import "@fontsource/roboto/400.css";
import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";

Basic use

All the components are isolated, self-supporting, and only inject styles that they need to present. To get things going, let’s use the example below, which creates a simple button component:

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>
  );
}
MUI Demo Button
A demo button built using MUI

The MUI 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, container and item. To make the layout fluid and adaptive to different screen sizes, the item widths are set in percentages, and padding creates spacing between each individual item. There are five types of grid breakpoints, including xs, sm, md, lg, and xl.

Import the Grid component

Import the Grid component into the JavaScript file using the following code:

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. Every item 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 each individual grid item. 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 MUI Spacing Value
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, and 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>
  );
}
Fluid Grids Scale Content Screen Size
Using fluid grids to scale content for different screen sizes

Auto-layout

The auto-layout feature allows the grid items to auto-resize and occupy 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>
  );
}
Auto Layout Perfect Layout
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 MUI
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 not using the spacing feature and implementing it in user space.  spacing={0} is the default. In addition, when applying a background color, first apply the display:flex style to the parent.

white-space no-wrap

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

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

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

Getting started with MUI Grid v2

At the time of writing, MUI Grid v2 was just released, offering some improvements over the original Grid system. Before releasing a stable version, the MUI team is still gathering feedback. To get the whole overview of the new version, feel free to visit the migration guide. We’ll have a quick look at the changes so that you can get started start with the new Grid system.

To import the new Grid version, run following code:

import Grid2 from '@mui/material/Unstable_Grid2'; // Grid version 2

One major change is that you can remove the item and zeroMinWidth prop from your Grid components, simplifying the logic with CSS variables and reducing the CSS specificity. So, instead of using <Grid item zeroMinWidth xs={6}>, you can now simply use <Grid XS={6} and achieve the same behavior.

The limitation regarding the negative margins is also addressed. To avoid a horizontal scroll bar appearing when, for example, the negative margin goes beyond the <body>, you can now use the disableEqualOverflow prop as follows:

import * as React from 'react';
import { styled } from '@mui/material/styles';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import Grid from '@mui/material/Unstable_Grid2';

const Item = styled(Paper)(({ theme }) => ({
  backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
  ...theme.typography.body2,
  padding: theme.spacing(1),
  textAlign: 'center',
  color: theme.palette.text.secondary,
}));

export default function AutoGrid() {
  return (
    <Box
      sx={(theme) => ({
        display: 'flex',
        flexDirection: 'column',
        gap: 3,
        width: 200,
        '& > div': {
          overflow: 'auto hidden',
          '&::-webkit-scrollbar': { height: 10, WebkitAppearance: 'none' },
          '&::-webkit-scrollbar-thumb': {
            borderRadius: 8,
            border: '2px solid',
            borderColor: theme.palette.mode === 'dark' ? '' : '#E7EBF0',
            backgroundColor: 'rgba(0 0 0 / 0.5)',
          },
        },
      })}
    >
      <div>
        <Grid container spacing={3}>
          <Grid xs={12}>
            <Item>Scroll bar appears</Item>
          </Grid>
        </Grid>
      </div>
      <div>
        <Grid container spacing={3} disableEqualOverflow>
          <Grid xs={12}>
            <Item>`disableEqualOverflow` prevents scrollbar</Item>
          </Grid>
        </Grid>
      </div>
    </Box>
  );
}

Disable Equal Overflow Avoid Horizontal Scrollbar

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.

Get setup with LogRocket's modern React error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    LogRocket.init('app/id');
    Add to your HTML:

    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • ngrx middleware
    • Vuex plugin
Get started now
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 “Guide 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