Grid
The responsive layout grid adapts to screen size and orientation, ensuring consistency across layouts.
The Grid component works well for a layout with known columns. The columns can be configured in multiple breakpoints which you have to specify the column span of each child.
How it works
The grid system is implemented with the Grid component:
- It uses CSS's Flexible Box module for high flexibility.
- The grid is always a flex item. Use the
containerprop to add flex container to it. - Item widths are set in percentages, so they're always fluid and sized relative to their parent element.
- There are five default grid breakpoints: xs, sm, md, lg, and xl. If you need custom breakpoints, check out custom breakpoints grid.
- Integer values can be given to each breakpoint, indicating how many of the 12 available columns are occupied by the component when the viewport width satisfies the breakpoint constraints.
- It does not have the concept of rows. Meaning, you can't make the children span to multiple rows. If you need to do that, we recommend using CSS Grid instead.
- It does not offer auto-placement children feature. It will try to fit the children one by one and if there is not enough space, the rest of the children will start on the next line and so on. If you need the auto-placement feature, we recommend using CSS Grid instead.
Fluid grids
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.
Basic grid
In order to create a grid layout, you need a container. Use 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 Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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>
);
}
Multiple breakpoints
Components may have multiple widths defined, causing the layout to change at the defined breakpoint. Width values given to larger breakpoints override those given to smaller breakpoints.
For example, size={{ xs: 12, sm: 6 }} sizes a component to occupy half of the viewport width (6 columns) when viewport width is 600 or more pixels. For smaller viewports, the component fills all 12 available columns.
import Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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>
);
}
Spacing
To control space between children, use the spacing prop.
The spacing value can be any positive number, including decimals and any string.
The prop is converted into a CSS property using the theme.spacing() helper.
<Grid container spacing={2}>import * as React from 'react';
import Grid from '@mui/system/Grid';
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/internal-core-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 (
<Grid sx={{ flexGrow: 1 }} container spacing={2}>
<Grid size={12}>
<Grid container spacing={spacing} sx={{ justifyContent: 'center' }}>
{[0, 1, 2].map((value) => (
<Grid key={value}>
<Paper
sx={(theme) => ({
height: 140,
width: 100,
backgroundColor: '#fff',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
}),
})}
/>
</Grid>
))}
</Grid>
</Grid>
<Grid size={12}>
<Paper sx={{ p: 2 }}>
<Grid container>
<Grid>
<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 allow for specifying the row and column gaps independently.
It's similar to the row-gap and column-gap properties of CSS Grid.
import styled from '@mui/system/styled';
import Grid from '@mui/system/Grid';
import Box from '@mui/system/Box';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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>
);
}
Responsive values
You can switch the props' value based on the active breakpoint. For instance, we can implement the recommended responsive layout grid of Material Design.
import Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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 }}>
<Item>{index + 1}</Item>
</Grid>
))}
</Grid>
</Box>
);
}
Responsive values is supported by:
sizecolumnscolumnSpacingdirectionrowSpacingspacingoffset- all the other props of MUI System
Auto-layout
The Auto-layout makes the items equitably share the available space. That also means you can set the width of one item and the others will automatically resize around it.
import Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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>
);
}
Variable width content
Set one of the size breakpoint props to "auto" to size a column based on the width of its content.
import Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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>
);
}
Nested Grid
The grid container that renders inside another grid container is a nested grid which inherits the columns and spacing from the top. The deep nested grid will inherit the props from the upper nested grid if it receives those props.
- Link 1.1
- Link 1.2
- Link 1.3
- Link 2.1
- Link 2.2
- Link 2.3
- Link 3.1
- Link 3.2
- Link 3.3
- Link 4.1
- Link 4.2
- Link 4.3
import Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
border: '1px solid',
borderColor: '#ced7e0',
borderRadius: '4px',
...theme.applyStyles('dark', {
borderColor: '#444d58',
}),
}));
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
sx={{
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: { xs: 'column', sm: 'row' },
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>
);
}
Columns
You can change the default number of columns (12) with the columns prop.
import Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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>
);
}
Offset
Move the item to the right by using the offset prop which can be:
- number, for example,
offset={{ md: 2 }}- when used the item is moved to the right by 2 columns starts frommdbreakpoint and up. "auto"- when used, the item is moved to the right edge of the grid container.
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
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>
);
}
Custom breakpoints
If you specify custom breakpoints to the theme, you can use those names as grid item props in responsive values.
import { ThemeProvider, createTheme } from '@mui/system';
import Box from '@mui/system/Box';
import Grid from '@mui/system/Grid';
import styled from '@mui/system/styled';
const Item = styled('div')(({ theme }) => ({
backgroundColor: '#fff',
border: '1px solid',
borderColor: '#ced7e0',
padding: theme.spacing(1),
borderRadius: '4px',
textAlign: 'center',
...theme.applyStyles('dark', {
backgroundColor: '#1A2027',
borderColor: '#444d58',
}),
}));
export default function CustomBreakpointsGrid() {
return (
<ThemeProvider
theme={createTheme({
breakpoints: {
values: {
laptop: 1024,
tablet: 640,
mobile: 0,
desktop: 1280,
},
},
})}
>
<Box sx={{ flexGrow: 1 }}>
<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,
}}
>
<Item>{index + 1}</Item>
</Grid>
))}
</Grid>
</Box>
</ThemeProvider>
);
}
TypeScript
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;
}
}
Limitations
direction column and column-reverse
The size and offset props are not supported within direction="column" and direction="column-reverse" containers.
They define the number of grids the component will use for a given breakpoint. They are intended to control width using flex-basis in row containers but they will impact height in column containers.
If used, these props may have undesirable effects on the height of the Grid item elements.