The sx prop
The sx prop is a shortcut for defining custom styles that has access to the theme.
The sx prop lets you work with a superset of CSS that packages all of the style functions exposed in @mui/system. You can specify any valid CSS using this prop, as well as many theme-aware properties that are unique to MUI System.
Basic example
The following demo illustrates how to work with the sx prop. Note that not all of the values are valid CSS properties—that's because the sx keys are mapped to specific properties of the theme. The rest of this document explores this concept in more detail.
import * as React from 'react';
import { Box, ThemeProvider, createTheme } from '@mui/system';
const theme = createTheme({
palette: {
background: {
paper: '#fff',
},
text: {
primary: '#173A5E',
secondary: '#46505A',
},
action: {
active: '#001E3C',
},
success: {
dark: '#009688',
},
},
});
export default function Example() {
return (
<ThemeProvider theme={theme}>
<Box
sx={{
bgcolor: 'background.paper',
boxShadow: 1,
borderRadius: 2,
p: 2,
minWidth: 300,
}}
>
<Box sx={{ color: 'text.secondary' }}>Sessions</Box>
<Box sx={{ color: 'text.primary', fontSize: 34, fontWeight: 'medium' }}>
98.3 K
</Box>
<Box
sx={{
color: 'success.dark',
display: 'inline',
fontWeight: 'bold',
mx: 0.5,
fontSize: 14,
}}
>
+18.77%
</Box>
<Box sx={{ color: 'text.secondary', display: 'inline', fontSize: 14 }}>
vs. last week
</Box>
</Box>
</ThemeProvider>
);
}Theme-aware properties
Borders
The border property can only receive a number as a value. It creates a solid black border using the number to define the width in pixels:
<Box sx={{ border: 1 }} />
// 对应生成的border样式: '1px solid black'
The borderColor property can receive a string, which represents the path in theme.palette:
<Box sx={{ borderColor: 'primary.main' }} />
// 默认生成的边框颜色:theme => theme.palette.primary.main
The borderRadius property multiplies the value it receives by the theme.shape.borderRadius value (the default for this value is 4px).
<Box sx={{ borderRadius: 2 }} />
// 对应生成的borderRadius为:theme => 2 * theme.shape.borderRadius
Read more on the Borders page.
Display
The displayPrint property allows you to specify a CSS display value that will only be applied when printing:
<Box sx={{ displayPrint: 'none' }} /> // 生成对应样式 '@media print': { display: 'none' }
Read more on the Display page.
Grid
The CSS Grid properties gap, rowGap and columnGap multiply the values they receive by the theme.spacing value (the default for the value is 8px).
<Box sx={{ gap: 2 }} />
// equivalent to gap: theme => theme.spacing(2)
Read more on the Grid page.
Palette
The color and backgroundColor properties can receive a string, which represents the path in theme.palette:
<Box sx={{ color: 'primary.main' }} />
// equivalent to color: theme => theme.palette.primary.main
The backgroundColor property is also available through its alias bgcolor:
<Box sx={{ bgcolor: 'primary.main' }} />
// equivalent to backgroundColor: theme => theme.palette.primary.main
Read more on the Palette page.
Positions
The zIndex property maps its value to the theme.zIndex value:
<Box sx={{ zIndex: 'tooltip' }} />
// equivalent to zIndex: theme => theme.zIndex.tooltip
Read more on the Positions page.
Shadows
The boxShadow property maps its value to the theme.shadows value:
<Box sx={{ boxShadow: 1 }} />
// equivalent to boxShadow: theme => theme.shadows[1]
Read more on the Shadows page.
Sizing
The sizing properties width, height, minHeight, maxHeight, minWidth, and maxWidth use the following custom transform function for the value:
function transform(value) {
return value <= 1 && value !== 0 ? `${value * 100}%` : value;
}
If the value is between [0, 1], it's converted to a percentage. Otherwise, it is directly set on the CSS property:
<Box sx={{ width: 1/2 }} /> // equivalent to width: '50%'
<Box sx={{ width: 20 }} /> // equivalent to width: '20px'
Read more on the Sizing page.
Spacing
The spacing properties margin, padding, and the corresponding longhand properties multiply the values they receive by the theme.spacing value (the default for the value is 8px):
<Box sx={{ margin: 2 }} />
// equivalent to margin: theme => theme.spacing(2)
The following aliases are available for the spacing properties:
| Prop | CSS property |
|---|---|
m |
margin |
mt |
margin-top |
mr |
margin-right |
mb |
margin-bottom |
ml |
margin-left |
mx |
margin-left, margin-right |
my |
margin-top, margin-bottom |
p |
padding |
pt |
padding-top |
pr |
padding-right |
pb |
padding-bottom |
pl |
padding-left |
px |
padding-left, padding-right |
py |
padding-top, padding-bottom |
Read more on the Spacing page.
Typography
The fontFamily, fontSize, fontStyle, fontWeight properties map their value to the theme.typography value:
<Box sx={{ fontWeight: 'fontWeightLight' }} />
// equivalent to fontWeight: theme.typography.fontWeightLight
The same can be achieved by omitting the CSS property prefix fontWeight:
<Box sx={{ fontWeight: 'light' }} />
// equivalent to fontWeight: theme.typography.fontWeightLight
There is an additional typography prop available, which sets all values defined in the specific theme.typography variant:
<Box sx={{ typography: 'body1' }} />
// equivalent to { ...theme.typography.body1 }
Read more on the Typography page.
Responsive values
All properties associated with the sx prop also support responsive values for specific breakpoints.
Read more on the Usage page—Responsive values.
Callback values
Each property in the sx prop can receive a function callback as a value. This is useful when you want to use the theme for calculating a value:
<Box sx={{ height: (theme) => theme.spacing(10) }} />
The sx prop can also receive a callback when you need to get theme values that are objects:
<Box
sx={(theme) => ({
...theme.typography.body,
color: theme.palette.primary.main,
})}
/>
Array values
Array types are useful when you want to partially override some styles in the former index:
<Box
sx={[
{
'&:hover': {
color: 'red',
backgroundColor: 'white',
},
},
foo && {
'&:hover': { backgroundColor: 'grey' },
},
bar && {
'&:hover': { backgroundColor: 'yellow' },
},
]}
/>
When you hover on this element, color: red; backgroundColor: white; is applied.
If foo: true, then color: red; backgroundColor: grey; is applied when hovering.
If bar: true, then color: red; backgroundColor: yellow; is applied when hovering regardless of foo value, because the higher index of the array has higher specificity.
<Box
sx={[
{ mr: 2, color: 'red' },
(theme) => ({
'&:hover': {
color: theme.palette.primary.main,
},
}),
]}
/>
Passing the sx prop
If you want to receive the sx prop from a custom component and pass it down to an MUI component, we recommend this approach:
import * as React from 'react';
import ListItem from '@mui/material/ListItem';
import FormLabel from '@mui/material/FormLabel';
import { SxProps, Theme } from '@mui/material/styles';
interface ListHeaderProps {
children: React.ReactNode;
sx?: SxProps<Theme>;
}
function ListHeader({ sx = [], children }: ListHeaderProps) {
return (
<ListItem
sx={[
{
width: 'auto',
textDecoration: 'underline',
},
// You cannot spread `sx` directly because `SxProps` (typeof sx) can be an array.
...(Array.isArray(sx) ? sx : [sx]),
]}
>
<FormLabel sx={{ color: 'inherit' }}>{children}</FormLabel>
</ListItem>
);
}
export default function PassingSxProp() {
return (
<ListHeader
sx={(theme) => ({
color: 'info.main',
...theme.typography.overline,
})}
>
Header
</ListHeader>
);
}TypeScript usage
A frequent source of confusion with the sx prop is TypeScript's type widening, which causes this example not to work as expected:
const style = {
flexDirection: 'column',
};
export default function App() {
return <Button sx={style}>Example</Button>;
}
// Type '{ flexDirection: string; }' is not assignable to type 'SxProps<Theme> | undefined'.
// Type '{ flexDirection: string; }' is not assignable to type 'CSSSelectorObject<Theme>'.
// Property 'flexDirection' is incompatible with index signature.
// Type 'string' is not assignable to type 'SystemStyleObject<Theme>'.
The problem is that the type of the flexDirection prop is inferred as string, which is too wide. To fix this, you can cast the object/function passed to the sx prop to const:
const style = {
flexDirection: 'column',
} as const;
export default function App() {
return <Button sx={style}>Example</Button>;
}
Alternatively, you can pass the style object directly to the sx prop:
export default function App() {
return <Button sx={{ flexDirection: 'column' }}>Example</Button>;
}
Performance
To learn more about the performance tradeoffs of the sx prop, check out Usage–Performance tradeoffs.