The responsive layout grid adapts to screen size and orientation, ensuring consistency across layouts.
The Grid
component works well for a layout with a known number of columns.
The columns can be configured with multiple breakpoints to specify the column span of each child.
The grid system is implemented with the Grid
component:
container
prop to add a flex container.gap
CSS property to add spacing between items.The
Grid
component is a layout grid, not a data grid. If you need a data grid, check out the MUI XDataGrid
component.
Fluid grids use columns that scale and resize content. A fluid grid’s layout can use breakpoints to determine if the layout needs to change dramatically.
In order to create a grid layout, you need a container.
Use the container
prop to create a grid container that wraps the grid items (the Grid
is always an item).
Column widths are integer values between 1 and 12.
For example, an item with size={6}
occupies half of the grid container’s width.
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/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function BasicGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid size={8}>
<Item>size=8</Item>
</Grid>
<Grid size={4}>
<Item>size=4</Item>
</Grid>
<Grid size={4}>
<Item>size=4</Item>
</Grid>
<Grid size={8}>
<Item>size=8</Item>
</Grid>
</Grid>
</Box>
);
}
Items may have multiple widths defined, causing the layout to change at the defined breakpoint. Width values apply to all wider breakpoints, and larger breakpoints override those given to smaller breakpoints.
For example, a component with size={{ xs: 12, sm: 6 }}
occupies the entire viewport width when the viewport is less than 600 pixels wide.
When the viewport grows beyond this size, the component occupies half of the total width—six columns rather than 12.
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/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function FullWidthGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid size={{ xs: 6, md: 8 }}>
<Item>xs=6 md=8</Item>
</Grid>
<Grid size={{ xs: 6, md: 4 }}>
<Item>xs=6 md=4</Item>
</Grid>
<Grid size={{ xs: 6, md: 4 }}>
<Item>xs=6 md=4</Item>
</Grid>
<Grid size={{ xs: 6, md: 8 }}>
<Item>xs=6 md=8</Item>
</Grid>
</Grid>
</Box>
);
}
Use the spacing
prop to control the space between children.
The spacing value can be any positive number (including decimals) or a string.
The prop is converted into a CSS property using the theme.spacing()
helper.
The following demo illustrates the use of the spacing
prop:
import * as React from 'react';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid2';
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 '@mui/docs/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 (
<Box
sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
gap: 2,
pt: 2,
'&& pre': { margin: 0 },
}}
>
<Grid container justifyContent="center" spacing={spacing}>
{[0, 1, 2].map((value) => (
<Grid key={value}>
<Paper
sx={(theme) => ({
height: 140,
width: 100,
backgroundColor: '#fff',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
})}
/>
</Grid>
))}
</Grid>
<Paper sx={{ p: 2 }}>
<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>
</Paper>
<HighlightedCode code={jsx} language="jsx" />
</Box>
);
}
The rowSpacing
and columnSpacing
props let you specify row and column gaps independently of one another.
They behave similarly to the row-gap
and column-gap
properties of CSS Grid.
import * as React from 'react';
import { styled } from '@mui/material/styles';
import Grid from '@mui/material/Grid2';
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.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 size={6}>
<Item>1</Item>
</Grid>
<Grid size={6}>
<Item>2</Item>
</Grid>
<Grid size={6}>
<Item>3</Item>
</Grid>
<Grid size={6}>
<Item>4</Item>
</Grid>
</Grid>
</Box>
);
}
You can set prop values to change when a given breakpoint is active. For instance, we can implement Material Design’s recommended responsive layout grid, as seen in the following demo:
import * as React from 'react';
import { experimentalStyled as styled } from '@mui/material/styles';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import Grid from '@mui/material/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(2),
textAlign: 'center',
color: 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 key={index} size={{ xs: 2, sm: 4, md: 4 }}>
<Item>{index + 1}</Item>
</Grid>
))}
</Grid>
</Box>
);
}
Responsive values are supported by:
size
columns
columnSpacing
direction
rowSpacing
spacing
offset
The auto-layout feature gives equal space to all items present. When you set the width of one item, the others will automatically resize to match it.
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/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function AutoGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={3}>
<Grid size="grow">
<Item>size=grow</Item>
</Grid>
<Grid size={6}>
<Item>size=6</Item>
</Grid>
<Grid size="grow">
<Item>size=grow</Item>
</Grid>
</Grid>
</Box>
);
}
When a breakpoint’s value is given as "auto"
, then a column’s size will automatically adjust to match the width of its content.
The demo below shows how this works:
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/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function VariableWidthGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={3}>
<Grid size="auto">
<Item>size=auto</Item>
</Grid>
<Grid size={6}>
<Item>size=6</Item>
</Grid>
<Grid size="grow">
<Item>size=grow</Item>
</Grid>
</Grid>
</Box>
);
}
The grid container that renders as a direct child inside another grid container is a nested grid that inherits its columns
and spacing
from the top level.
It will also inherit the props of the top-level grid if it receives those props.
:::success
Note that a nested grid container should be a direct child of another grid container. If there are non-grid elements in between, the grid container will start as the new root container.
<Grid container>
<Grid container> // A nested grid container that inherits columns and spacing from above.
<div>
<Grid container> // A new root grid container with its own variables scope.
:::
A nested grid container inherits the row and column spacing from its parent unless the spacing
prop is specified to the instance.
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/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function NestedGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid size={{ xs: 12, md: 5, lg: 4 }}>
<Item>Email subscribe section</Item>
</Grid>
<Grid container spacing={4} size={{ xs: 12, md: 7, lg: 8 }}>
<Grid size={{ xs: 6, lg: 3 }}>
<Item>
<Box
id="category-a"
sx={{ fontSize: '12px', textTransform: 'uppercase' }}
>
Category A
</Box>
<Box component="ul" aria-labelledby="category-a" sx={{ pl: 2 }}>
<li>Link 1.1</li>
<li>Link 1.2</li>
<li>Link 1.3</li>
</Box>
</Item>
</Grid>
<Grid size={{ xs: 6, lg: 3 }}>
<Item>
<Box
id="category-b"
sx={{ fontSize: '12px', textTransform: 'uppercase' }}
>
Category B
</Box>
<Box component="ul" aria-labelledby="category-b" sx={{ pl: 2 }}>
<li>Link 2.1</li>
<li>Link 2.2</li>
<li>Link 2.3</li>
</Box>
</Item>
</Grid>
<Grid size={{ xs: 6, lg: 3 }}>
<Item>
<Box
id="category-c"
sx={{ fontSize: '12px', textTransform: 'uppercase' }}
>
Category C
</Box>
<Box component="ul" aria-labelledby="category-c" sx={{ pl: 2 }}>
<li>Link 3.1</li>
<li>Link 3.2</li>
<li>Link 3.3</li>
</Box>
</Item>
</Grid>
<Grid size={{ xs: 6, lg: 3 }}>
<Item>
<Box
id="category-d"
sx={{ fontSize: '12px', textTransform: 'uppercase' }}
>
Category D
</Box>
<Box component="ul" aria-labelledby="category-d" sx={{ pl: 2 }}>
<li>Link 4.1</li>
<li>Link 4.2</li>
<li>Link 4.3</li>
</Box>
</Item>
</Grid>
</Grid>
<Grid
container
justifyContent="space-between"
alignItems="center"
flexDirection={{ xs: 'column', sm: 'row' }}
sx={{ fontSize: '12px' }}
size={12}
>
<Grid sx={{ order: { xs: 2, sm: 1 } }}>
<Item>© Copyright</Item>
</Grid>
<Grid container columnSpacing={1} sx={{ order: { xs: 1, sm: 2 } }}>
<Grid>
<Item>Link A</Item>
</Grid>
<Grid>
<Item>Link B</Item>
</Grid>
<Grid>
<Item>Link C</Item>
</Grid>
</Grid>
</Grid>
</Grid>
</Box>
);
}
A nested grid container inherits the columns from its parent unless the columns
prop is specified to the instance.
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/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function NestedGridColumns() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2} columns={24}>
<Grid size={8}>
<Item>size=8/24</Item>
</Grid>
<Grid container size={16}>
<Grid size={12}>
<Item>nested size=12/24</Item>
</Grid>
<Grid size={12}>
<Item>nested size=12/24</Item>
</Grid>
</Grid>
<Grid size={8}>
<Item>size=8/24</Item>
</Grid>
<Grid container columns={12} size={16}>
<Grid size={6}>
<Item>nested size=6/12</Item>
</Grid>
<Grid size={6}>
<Item>nested size=6/12</Item>
</Grid>
</Grid>
</Grid>
</Box>
);
}
Use the columns
prop to change the default number of columns (12) in the grid, as shown below:
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/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: 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 size={8}>
<Item>size=8</Item>
</Grid>
<Grid size={8}>
<Item>size=8</Item>
</Grid>
</Grid>
</Box>
);
}
The offset
prop pushes an item to the right side of the grid.
This props accepts:
offset={{ md: 2 }}
pushes an item two columns to the right when the viewport size is equal to or greater than the md
breakpoint."auto"
—this pushes the item to the far right side of the grid container.The demo below illustrates how to use the offset props:
import * as React from 'react';
import { styled } from '@mui/material/styles';
import Paper from '@mui/material/Paper';
import Grid from '@mui/material/Grid2';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
}));
export default function OffsetGrid() {
return (
<Grid container spacing={3} sx={{ flexGrow: 1 }}>
<Grid size={{ xs: 6, md: 2 }} offset={{ xs: 3, md: 0 }}>
<Item>1</Item>
</Grid>
<Grid size={{ xs: 4, md: 2 }} offset={{ md: 'auto' }}>
<Item>2</Item>
</Grid>
<Grid size={{ xs: 4, md: 2 }} offset={{ xs: 4, md: 0 }}>
<Item>3</Item>
</Grid>
<Grid size={{ xs: 'grow', md: 6 }} offset={{ md: 2 }}>
<Item>4</Item>
</Grid>
</Grid>
);
}
If you specify custom breakpoints in the theme, you can use those names as grid item props in responsive values:
import { ThemeProvider, createTheme } from '@mui/material/styles';
function Demo() {
return (
<ThemeProvider
theme={createTheme({
breakpoints: {
values: {
laptop: 1024,
tablet: 640,
mobile: 0,
desktop: 1280,
},
},
})}
>
<Grid container spacing={{ mobile: 1, tablet: 2, laptop: 3 }}>
{Array.from(Array(4)).map((_, index) => (
<Grid key={index} size={{ mobile: 6, tablet: 4, laptop: 3 }}>
<div>{index + 1}</div>
</Grid>
))}
</Grid>
</ThemeProvider>
);
}
Custom breakpoints affect all responsive values.
You have to set module augmentation on the theme breakpoints interface.
declare module '@mui/system' {
interface BreakpointOverrides {
// Your custom breakpoints
laptop: true;
tablet: true;
mobile: true;
desktop: true;
// Remove default breakpoints
xs: false;
sm: false;
md: false;
lg: false;
xl: false;
}
}
To center a grid item’s content, specify display="flex"
directly on the item.
Then use justifyContent
and/or alignItems
to adjust the position of the content, as shown below:
import * as React from 'react';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid2';
export default function CenteredElementGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2} minHeight={160}>
<Grid display="flex" justifyContent="center" alignItems="center" size="grow">
<Avatar src="/static/images/avatar/1.jpg" />
</Grid>
<Grid display="flex" justifyContent="center" alignItems="center">
<Avatar src="/static/images/avatar/2.jpg" />
</Grid>
<Grid display="flex" justifyContent="center" alignItems="center" size="grow">
<Avatar src="/static/images/avatar/3.jpg" />
</Grid>
</Grid>
</Box>
);
}
Using the
container
prop does not work in this situation because the grid container is designed exclusively to wrap grid items. It cannot wrap other elements.
{{“demo”: “FullBorderedGrid.js”}}
{{“demo”: “HalfBorderedGrid.js”}}
The size
and offset
props are not supported within containers that use direction="column"
or direction="column-reverse"
.
Size and offset props define the number of columns the component will use for a given breakpoint.
They are intended to control the width using flex-basis
in row
containers, but they will impact the height in column
containers.
If used, these props may have undesirable effects on the height of the Grid
item elements.