DEV Community

Cover image for The Material-UI grid system
Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

The Material-UI grid system

Written by Gaurav Singhal✏️

Material-UI 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 Material-UI and its grid system and show how you 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 the design system, making it more flexible for designers to create custom themes on top of Material-UI.

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

LogRocket Free Trial Banner

Material-UI’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.

npm install @material-ui/core
Enter fullscreen mode Exit fullscreen mode

Material-UI 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"
/>
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

The grid component

The 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";
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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 { 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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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

Alt Text

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 — start monitoring for free.


The post The Material-UI grid system appeared first on LogRocket Blog.

Top comments (0)