Reference
GridLegacy
The Material Design responsive layout grid adjusts to different screen sizes and orientations, maintaining uniformity across layouts.
The grid ensures visual harmony across layouts while supporting flexibility for a wide range of designs. Material Design's responsive UI relies on a 12-column grid system.
:::warning The
GridLegacy
component is not intended to function as a data grid; it serves as a layout grid. For a data grid, refer to the DataGrid
component. ::::::warning The
GridLegacy
component is deprecated. It is recommended to use Grid instead. Consult the Grid upgrade guide for additional information. :::How it works
The grid system is built using the
GridLegacy
component:- It leverages CSS Flexible Box module for enhanced flexibility.
- There are two layout types: containers and items.
- Item widths are defined in percentages, ensuring they remain fluid and scale relative to their parent container.
- Items include padding to establish spacing between individual elements.
- Five grid breakpoints are available: xs, sm, md, lg, and xl.
- Each breakpoint can be assigned integer values to specify how many of the 12 columns a component occupies when the viewport width meets the breakpoint constraints.
If you are new to or unfamiliar with flexbox, we recommend reviewing this CSS-Tricks flexbox guide.
Fluid grids
Fluid grids utilize columns that adjust and resize content dynamically. The layout of a fluid grid can employ breakpoints to determine when significant layout changes are needed.
Basic grid
Column widths are set as integer values from 1 to 12, applicable at any breakpoint, indicating the number of columns a component occupies.
A value assigned to a breakpoint applies to all wider breakpoints unless explicitly overridden. For instance,
xs={12}
ensures a component spans the entire width of its parent container across all viewport sizes.xs=8
xs=4
xs=4
xs=8
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/GridLegacy'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function BasicGrid() { return ( <Box sx={{ flexGrow: 1 }}> <Grid container spacing={2}> <Grid item xs={8}> <Item>xs=8</Item> </Grid> <Grid item xs={4}> <Item>xs=4</Item> </Grid> <Grid item xs={4}> <Item>xs=4</Item> </Grid> <Grid item xs={8}> <Item>xs=8</Item> </Grid> </Grid> </Box> ); }
Grid with multiple breakpoints
Components can have multiple widths defined, triggering layout changes at specified breakpoints. Values set for larger breakpoints take precedence over those for smaller ones.
For example,
xs={12} sm={6}
makes a component occupy half the viewport width (6 columns) when the viewport is 600 pixels or wider. For smaller viewports, it spans all 12 columns.xs=6 md=8
xs=6 md=4
xs=6 md=4
xs=6 md=8
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/GridLegacy'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function FullWidthGrid() { return ( <Box sx={{ flexGrow: 1 }}> <Grid container spacing={2}> <Grid item xs={6} md={8}> <Item>xs=6 md=8</Item> </Grid> <Grid item xs={6} md={4}> <Item>xs=6 md=4</Item> </Grid> <Grid item xs={6} md={4}> <Item>xs=6 md=4</Item> </Grid> <Grid item xs={6} md={8}> <Item>xs=6 md=8</Item> </Grid> </Grid> </Box> ); }
Spacing
To manage spacing between child elements, use the
spacing
prop. This value can be any positive number, including decimals, or any string, and is transformed into a CSS property via the theme.spacing()
helper.<Grid container spacing={2}>
import * as React from 'react'; import Grid from '@mui/material/GridLegacy'; import FormLabel from '@mui/material/FormLabel'; import FormControl from '@mui/material/FormControl'; import FormControlLabel from '@mui/material/FormControlLabel'; import RadioGroup from '@mui/material/RadioGroup'; import Radio from '@mui/material/Radio'; import Paper from '@mui/material/Paper'; import { HighlightedCode } from '@/app/(public)/documentation/material-ui-components/utils/HighlightedCode'; export default function SpacingGrid() { const [spacing, setSpacing] = React.useState(2); const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { setSpacing(Number((event.target as HTMLInputElement).value)); }; const jsx = ` <Grid container spacing={${spacing}}> `; return ( <Grid sx={{ flexGrow: 1 }} container spacing={2}> <Grid item xs={12}> <Grid container spacing={spacing} sx={{ justifyContent: 'center' }}> {[0, 1, 2].map((value) => ( <Grid key={value} item> <Paper sx={(theme) => ({ height: 140, width: 100, backgroundColor: '#fff', ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })} /> </Grid> ))} </Grid> </Grid> <Grid item xs={12}> <Paper sx={{ p: 2 }}> <Grid container> <Grid item> <FormControl component="fieldset"> <FormLabel component="legend">spacing</FormLabel> <RadioGroup name="spacing" aria-label="spacing" value={spacing.toString()} onChange={handleChange} row > {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => ( <FormControlLabel key={value} value={value.toString()} control={<Radio />} label={value.toString()} /> ))} </RadioGroup> </FormControl> </Grid> </Grid> </Paper> <HighlightedCode code={jsx} language="jsx" /> </Grid> </Grid> ); }
Row & column spacing
The
rowSpacing
and columnSpacing
props enable independent control over row and column gaps, similar to the row-gap
and column-gap
properties in CSS Grid.1
2
3
4
import * as React from 'react'; import { styled } from '@mui/material/styles'; import Grid from '@mui/material/GridLegacy'; import Paper from '@mui/material/Paper'; import Box from '@mui/material/Box'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function RowAndColumnSpacing() { return ( <Box sx={{ width: '100%' }}> <Grid container rowSpacing={1} columnSpacing={{ xs: 1, sm: 2, md: 3 }}> <Grid item xs={6}> <Item>1</Item> </Grid> <Grid item xs={6}> <Item>2</Item> </Grid> <Grid item xs={6}> <Item>3</Item> </Grid> <Grid item xs={6}> <Item>4</Item> </Grid> </Grid> </Box> ); }
Responsive values
Props can dynamically adjust their values based on the active breakpoint. For example, this allows implementation of Material Design's "recommended" responsive layout grid.
xs=2
xs=2
xs=2
xs=2
xs=2
xs=2
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/GridLegacy'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(2), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function ResponsiveGrid() { return ( <Box sx={{ flexGrow: 1 }}> <Grid container spacing={{ xs: 2, md: 3 }} columns={{ xs: 4, sm: 8, md: 12 }}> {Array.from(Array(6)).map((_, index) => ( <Grid item xs={2} sm={4} md={4} key={index}> <Item>xs=2</Item> </Grid> ))} </Grid> </Box> ); }
Responsive values are supported for:
columns
columnSpacing
direction
rowSpacing
spacing
- all the other props of MUI System
:::warning When using a responsive
columns
prop, each grid item must have a corresponding value for every breakpoint. For example, this will not work, as the grid item lacks a value for md
:<Grid container columns={{ xs: 4, md: 12 }}> <Grid item xs={2} /> </Grid>
:::
Interactive
The following interactive demo allows you to experiment with various settings and observe their visual outcomes:
Cell 1
Cell 2
Cell 3
<Grid container direction="row" sx={{ justifyContent: "center", alignItems: "center", }} >
import * as React from 'react'; import Grid, { GridLegacyDirection } from '@mui/material/GridLegacy'; import FormControl from '@mui/material/FormControl'; 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'; import { HighlightedCode } from '@/app/(public)/documentation/material-ui-components/utils/HighlightedCode'; type GridItemsAlignment = | 'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'; type GridJustification = | 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'; export default function InteractiveGrid() { const [direction, setDirection] = React.useState<GridLegacyDirection>('row'); const [justifyContent, setJustifyContent] = React.useState<GridJustification>('center'); const [alignItems, setAlignItems] = React.useState<GridItemsAlignment>('center'); const jsx = ` <Grid container direction="${direction}" sx={{ justifyContent: "${justifyContent}", alignItems: "${alignItems}", }} > `; return ( <Grid sx={{ flexGrow: 1 }} container> <Grid item xs={12}> <Grid container spacing={2} direction={direction} sx={{ alignItems, justifyContent, height: 300, pb: 2 }} > {[0, 1, 2].map((value) => ( <Grid key={value} item> <Paper sx={(theme) => ({ p: 2, backgroundColor: '#fff', height: '100%', color: 'text.secondary', pt: `${(value + 1) * 10}px`, pb: `${(value + 1) * 10}px`, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })} > {`Cell ${value + 1}`} </Paper> </Grid> ))} </Grid> </Grid> <Grid item xs={12}> <Paper sx={{ p: 2 }}> <Grid container spacing={3}> <Grid item xs={12}> <FormControl component="fieldset"> <FormLabel component="legend">direction</FormLabel> <RadioGroup row name="direction" aria-label="direction" value={direction} onChange={(event) => { setDirection( (event.target as HTMLInputElement) .value as GridLegacyDirection, ); }} > <FormControlLabel value="row" control={<Radio />} label="row" /> <FormControlLabel value="row-reverse" control={<Radio />} label="row-reverse" /> <FormControlLabel value="column" control={<Radio />} label="column" /> <FormControlLabel value="column-reverse" control={<Radio />} label="column-reverse" /> </RadioGroup> </FormControl> </Grid> <Grid item xs={12}> <FormControl component="fieldset"> <FormLabel component="legend">justifyContent</FormLabel> <RadioGroup row name="justifyContent" aria-label="justifyContent" value={justifyContent} onChange={(event) => { setJustifyContent( (event.target as HTMLInputElement).value as GridJustification, ); }} > <FormControlLabel value="flex-start" control={<Radio />} label="flex-start" /> <FormControlLabel value="center" control={<Radio />} label="center" /> <FormControlLabel value="flex-end" control={<Radio />} label="flex-end" /> <FormControlLabel value="space-between" control={<Radio />} label="space-between" /> <FormControlLabel value="space-around" control={<Radio />} label="space-around" /> <FormControlLabel value="space-evenly" control={<Radio />} label="space-evenly" /> </RadioGroup> </FormControl> </Grid> <Grid item xs={12}> <FormControl component="fieldset"> <FormLabel component="legend">alignItems</FormLabel> <RadioGroup row name="alignItems" aria-label="align items" value={alignItems} onChange={(event) => { setAlignItems( (event.target as HTMLInputElement).value as GridItemsAlignment, ); }} > <FormControlLabel value="flex-start" control={<Radio />} label="flex-start" /> <FormControlLabel value="center" control={<Radio />} label="center" /> <FormControlLabel value="flex-end" control={<Radio />} label="flex-end" /> <FormControlLabel value="stretch" control={<Radio />} label="stretch" /> <FormControlLabel value="baseline" control={<Radio />} label="baseline" /> </RadioGroup> </FormControl> </Grid> </Grid> </Paper> </Grid> <Grid item xs={12}> <HighlightedCode code={jsx} language="jsx" /> </Grid> </Grid> ); }
Auto-layout
The Auto-layout feature enables items to evenly distribute available space. This means you can define the width of one item, and the others will automatically adjust around it.
xs
xs=6
xs
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/GridLegacy'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function AutoGrid() { return ( <Box sx={{ flexGrow: 1 }}> <Grid container spacing={3}> <Grid item xs> <Item>xs</Item> </Grid> <Grid item xs={6}> <Item>xs=6</Item> </Grid> <Grid item xs> <Item>xs</Item> </Grid> </Grid> </Box> ); }
Variable width content
By setting a size breakpoint prop to
"auto"
instead of true
or a number
, a column can be sized based on the natural width of its content.variable width content
xs=6
xs
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/GridLegacy'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function VariableWidthGrid() { return ( <Box sx={{ flexGrow: 1 }}> <Grid container spacing={3}> <Grid item xs="auto"> <Item>variable width content</Item> </Grid> <Grid item xs={6}> <Item>xs=6</Item> </Grid> <Grid item xs> <Item>xs</Item> </Grid> </Grid> </Box> ); }
Complex Grid
The following example deviates from Material Design guidelines but demonstrates how the grid can be utilized to create intricate layouts.
Standard license
Full resolution 1920x1080 • JPEG
ID: 1030114
Remove
$19.00
import * as React from 'react'; import { styled } from '@mui/material/styles'; import Grid from '@mui/material/GridLegacy'; import Paper from '@mui/material/Paper'; import Typography from '@mui/material/Typography'; import ButtonBase from '@mui/material/ButtonBase'; const Img = styled('img')({ margin: 'auto', display: 'block', maxWidth: '100%', maxHeight: '100%', }); export default function ComplexGrid() { return ( <Paper sx={(theme) => ({ p: 2, margin: 'auto', maxWidth: 500, flexGrow: 1, backgroundColor: '#fff', ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })} > <Grid container spacing={2}> <Grid item> <ButtonBase sx={{ width: 128, height: 128 }}> <Img alt="complex" src="/material-ui-static/images/grid/complex.jpg" /> </ButtonBase> </Grid> <Grid item xs={12} sm container> <Grid item xs container direction="column" spacing={2}> <Grid item xs> <Typography gutterBottom variant="subtitle1" component="div"> Standard license </Typography> <Typography variant="body2" gutterBottom> Full resolution 1920x1080 • JPEG </Typography> <Typography variant="body2" sx={{ color: 'text.secondary' }}> ID: 1030114 </Typography> </Grid> <Grid item> <Typography sx={{ cursor: 'pointer' }} variant="body2"> Remove </Typography> </Grid> </Grid> <Grid item> <Typography variant="subtitle1" component="div"> $19.00 </Typography> </Grid> </Grid> </Grid> </Paper> ); }
Nested Grid
The
container
and item
props are independent booleans, allowing a Grid component to function as both a flex container and a child simultaneously.A flex container is an element with a computed display of
flex
or inline-flex
. Its in-flow children, known as flex items, are arranged using the flex layout model.Item
Item
Item
Item
Item
Item
Item
Item
Item
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/GridLegacy'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); function FormRow() { return ( <React.Fragment> <Grid item xs={4}> <Item>Item</Item> </Grid> <Grid item xs={4}> <Item>Item</Item> </Grid> <Grid item xs={4}> <Item>Item</Item> </Grid> </React.Fragment> ); } export default function NestedGrid() { return ( <Box sx={{ flexGrow: 1 }}> <Grid container spacing={1}> <Grid container item spacing={3}> <FormRow /> </Grid> <Grid container item spacing={3}> <FormRow /> </Grid> <Grid container item spacing={3}> <FormRow /> </Grid> </Grid> </Box> ); }
⚠️ Setting an explicit width on a Grid element that is simultaneously a flex container, flex item, and has spacing can result in unexpected behavior. Avoid combining these properties:
<Grid spacing={1} container item xs={12}>
If necessary, remove one of these props to prevent issues.
Columns
The default number of columns (12) can be modified using the
columns
prop.xs=8
xs=8
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/GridLegacy'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function ColumnsGrid() { return ( <Box sx={{ flexGrow: 1 }}> <Grid container spacing={2} columns={16}> <Grid item xs={8}> <Item>xs=8</Item> </Grid> <Grid item xs={8}> <Item>xs=8</Item> </Grid> </Grid> </Box> ); }
Limitations
Negative margin
Item spacing is achieved using negative margins, which may cause unexpected results. For example, applying a background color requires setting
display: flex;
on the parent element.white-space: nowrap
Flex items have a default
min-width: auto
, which can conflict with children using white-space: nowrap;
. This issue can be replicated with:<Grid item xs> <Typography noWrap>
To keep the item within the container, set
min-width: 0
. In practice, use the zeroMinWidth
prop:<Grid item xs zeroMinWidth> <Typography noWrap>
W
Truncation should be conditionally applicable on this long line of text as this is a much longer line than what the container can support.
W
Truncation should be conditionally applicable on this long line of text as this is a much longer line than what the container can support.
W
Truncation should be conditionally applicable on this long line of text as this is a much longer line than what the container can support.
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/GridLegacy'; import Avatar from '@mui/material/Avatar'; import Typography from '@mui/material/Typography'; const StyledPaper = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(2), maxWidth: 400, color: (theme.vars ?? theme).palette.text.primary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); const message = `Truncation should be conditionally applicable on this long line of text as this is a much longer line than what the container can support. `; export default function AutoGridNoWrap() { return ( <Box sx={{ flexGrow: 1, overflow: 'hidden', px: 3 }}> <StyledPaper sx={{ my: 1, mx: 'auto', p: 2 }}> <Grid container spacing={2} wrap="nowrap"> <Grid item> <Avatar>W</Avatar> </Grid> <Grid item xs zeroMinWidth> <Typography noWrap>{message}</Typography> </Grid> </Grid> </StyledPaper> <StyledPaper sx={{ my: 1, mx: 'auto', p: 2 }}> <Grid container spacing={2} wrap="nowrap"> <Grid item> <Avatar>W</Avatar> </Grid> <Grid item xs> <Typography noWrap>{message}</Typography> </Grid> </Grid> </StyledPaper> <StyledPaper sx={{ my: 1, mx: 'auto', p: 2 }}> <Grid container spacing={2} wrap="nowrap"> <Grid item> <Avatar>W</Avatar> </Grid> <Grid item xs> <Typography>{message}</Typography> </Grid> </Grid> </StyledPaper> </Box> ); }
direction: column | column-reverse
The
xs
, sm
, md
, lg
, and xl
props are not supported in direction="column"
or direction="column-reverse"
containers.These props specify the number of grid columns a component occupies at a given breakpoint. They are designed to control width via
flex-basis
in row
containers but may affect height in column
containers, potentially causing undesirable effects on the height of GridLegacy
items.CSS Grid Layout
The
GridLegacy
component internally uses CSS flexbox. However, as demonstrated below, you can seamlessly utilize MUI System and CSS Grid to design your page layouts.xs=8
xs=4
xs=4
xs=8
import * as React from 'react'; import { styled } from '@mui/material/styles'; import Box from '@mui/material/Box'; import Paper from '@mui/material/Paper'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: '#fff', ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', color: (theme.vars ?? theme).palette.text.secondary, ...theme.applyStyles('dark', { backgroundColor: '#1A2027', }), })); export default function CSSGrid() { return ( <Box sx={{ width: 1 }}> <Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(12, 1fr)', gap: 2 }}> <Box sx={{ gridColumn: 'span 8' }}> <Item>xs=8</Item> </Box> <Box sx={{ gridColumn: 'span 4' }}> <Item>xs=4</Item> </Box> <Box sx={{ gridColumn: 'span 4' }}> <Item>xs=4</Item> </Box> <Box sx={{ gridColumn: 'span 8' }}> <Item>xs=8</Item> </Box> </Box> </Box> ); }
System props
System props are deprecated and will be discontinued in the next major release. Use the
sx
prop as an alternative.- <Grid item p={2} /> + <Grid item sx={{ p: 2 }} />