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.
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:
- 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
- Gutters — The spaces between the columns are defined by a fixed value at each breakpoint to better adapt the screen size
- 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
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"
/>
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
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";
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 { 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:
- Not using the spacing feature and implementing it in userspace
spacing={0}
(default)- Applying padding to the parent with at least half the spacing value applied to the child
- 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.
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)