Gaurav Singhal Guarav 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 Scrapping, Angular, and React.

The Material-UI grid system

6 min read 1697

The Material-UI Grid System

Material Design is a popular design system developed by Google in 2014. Since then, it has been widely used by designers and developers across the globe.

In this guide, we’ll explore the Material-UI library, which is a React library that implements Google’s Material Design and its grid system, and how we can use it to build applications with React.

Material Design

Material Design is a visual language that synthesizes the classic principles of good design with the innovation of technology and science. Widely used in Android app development, it defines a set of principles and guidelines for designing UI components.

Material Design comes with prebuilt UI components, including buttons, navbars, navigation drawers, and, most importantly, the grid system.

Google and many other tech companies use Material Design extensively across their brand and products. In 2018, Google revamped its design system, making it more flexible for designers to create custom themes. To facilitate new features, Material-UI also updated its libraries (v4).

That’s Material Design in a nutshell. Next, we’ll dig into the grid system, its features and limitations, and implementation in React.

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 Material-UI library

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

Installation

Run the following command to install material-ui as a dependency in your project.

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

npm install @material-ui/core

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 React from "react";
import Button from "@material-ui/core/Button";

function App() {
  return (
    <Button variant="contained" color="primary">
      Material Button Demo
    </Button>
  );
}

export default App;

The grid component

Material Design’s grid system is implemented in Material-UI using the <Grid /> component. Under the hood, the <Grid /> component uses Flexbox properties for high 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

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

import Grid from "@material-ui/core/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
  // ...
>
  <Grid
    item
    // ...
  >
    <Paper></Paper>
  </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 React from "react";
import Grid from "@material-ui/core/Grid";
import FormLabel from "@material-ui/core/FormLabel";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import RadioGroup from "@material-ui/core/RadioGroup";
import Radio from "@material-ui/core/Radio";
import Paper from "@material-ui/core/Paper";

const classes = {
  paper: {
    height: 140,
    width: 100
  },
  control: {
    padding: 20,
    marginTop: 15,
    background: "#fc3"
  }
};

export default function SpacingGridDemo() {
  const [spacing, setSpacing] = React.useState(2);

  const handleChange = event => {
    setSpacing(Number(event.target.value));
  };

  return (
    <div>
      <div>
        <Grid container justify="center" spacing={spacing}>
          {[0, 1, 2].map(value => (
            <Grid key={value} item>
              <Paper className={classes.paper} />
            </Grid>
          ))}
        </Grid>
      </div>
      <div>
        <Paper className={classes.control}>
          <div>
            <FormLabel>spacing</FormLabel>
            <RadioGroup
              name="spacing"
              aria-label="spacing"
              value={spacing.toString()}
              onChange={handleChange}
              row
            >
              {[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>
  );
}

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 React from "react";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";

const classes = {
  root: {
    flexGrow: 1
  },
  paper: {
    padding: 20,
    textAlign: "center",
    color: theme.palette.text.secondary,
    fontFamily: "Roboto"
  }
};

export default function BreakpointGridDemo() {
  return (
    <div className={classes.root}>
      <Grid container spacing={3}>
        <Grid item xs={12}>
          <Paper className={classes.paper}>xs=12</Paper>
        </Grid>
        <Grid item xs={12} sm={6}>
          <Paper className={classes.paper}>xs=12 sm=6</Paper>
        </Grid>
        <Grid item xs={12} sm={6}>
          <Paper className={classes.paper}>xs=12 sm=6</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper className={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper className={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper className={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
        <Grid item xs={6} sm={3}>
          <Paper className={classes.paper}>xs=6 sm=3</Paper>
        </Grid>
      </Grid>
    </div>
  );
}

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.

import React from "react";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";

const classes = {
  root: {
    flexGrow: 1
  },
  paper: {
    padding: 20,
    textAlign: "center"
  }
};

export default function AutoGridDemo() {
  return (
    <div className={classes.root}>
      <Grid container spacing={2}>
        <Grid item xs>
          <Paper className={classes.paper}>xs</Paper>
        </Grid>
        <Grid item xs>
          <Paper className={classes.paper}>xs</Paper>
        </Grid>
        <Grid item xs>
          <Paper className={classes.paper}>xs</Paper>
        </Grid>
      </Grid>
      <Grid container spacing={2}>
        <Grid item xs>
          <Paper className={classes.paper}>xs</Paper>
        </Grid>
        <Grid item xs>
          <Paper className={classes.paper}>xs</Paper>
        </Grid>
        <Grid item xs={9}>
          <Paper className={classes.paper}>xs=9</Paper>
        </Grid>
      </Grid>
    </div>
  );
}

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 React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";

const classes = {
  root: {
    flexGrow: 1
  },
  paper: {
    padding: 20,
    textAlign: "center",
    color: "#777"
  }
};

export default function NestedGridDemo() {
  function InnerGrid() {
    return (
      <React.Fragment>
        <Grid item xs={4}>
          <Paper className={classes.paper}>item</Paper>
        </Grid>
        <Grid item xs={4}>
          <Paper className={classes.paper}>item</Paper>
        </Grid>
        <Grid item xs={4}>
          <Paper className={classes.paper}>item</Paper>
        </Grid>
      </React.Fragment>
    );
  }

  return (
    <div className={classes.root}>
      <Grid container spacing={1}>
        <Grid container item xs={12} spacing={3}>
          <InnerGrid />
        </Grid>
        <Grid container item xs={12} spacing={3}>
          <InnerGrid />
        </Grid>
        <Grid container item xs={12} spacing={3}>
          <InnerGrid />
        </Grid>
      </Grid>
    </div>
  );
}

Limitations of Material-UI

Negative margin

Material-UI 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 Material-UI documentation suggests:

  1. Not using the spacing feature and implementing it in userspace spacing={0} (default)
  2. Applying padding to the parent with at least half the spacing value applied to the child
  3. Adding overflow-x: hidden; 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.

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 the column and column-reverse containers.

Conclusion

Despite the handful of drawbacks described above, Material-UI enable 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 difficult 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 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 Guarav 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 Scrapping, Angular, and React.

4 Replies to “The Material-UI 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