MUI v5+: Styling with the sx Prop, styled(), and Custom Themes
Material UI v5 replaced JSS and makeStyles with the sx prop and a styled() API built on Emotion — here is how to use them effectively.

Material UI (MUI) v5, released in late 2021, dropped JSS entirely in favor of Emotion as its default styling engine. If you're still reaching for makeStyles from @material-ui/core, you're on the deprecated v4 path. This guide covers how styling actually works in v5 and later.
Installation
npm install @mui/material @emotion/react @emotion/styledThe old @material-ui/core package is v4 and unmaintained. The current package is @mui/material.
The sx Prop — Your First Stop
The sx prop is a shorthand styling API available on every MUI component. It accepts standard CSS properties plus theme-aware shortcuts.
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
function Hero() {
return (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
bgcolor: 'background.paper',
p: 4, // 4 * 8px = 32px on all sides
borderRadius: 2,
boxShadow: 3,
}}
>
<Typography variant="h4" sx={{ color: 'primary.main', fontWeight: 'bold' }}>
Hello, MUI v5
</Typography>
<Typography sx={{ mt: 1, color: 'text.secondary' }}>
Styled with the sx prop.
</Typography>
</Box>
);
}Key sx shortcuts to know:
| Shorthand | CSS property | Example |
|-----------|-------------|---------|
| p / m | padding / margin | p: 2 → padding: 16px |
| px / py | padding horizontal/vertical | px: 3 |
| bgcolor | background-color | bgcolor: 'grey.100' |
| color | color (theme-aware) | color: 'primary.main' |
Responsive Values
The sx prop understands breakpoints natively:
<Box
sx={{
width: { xs: '100%', sm: '50%', md: '33%' },
display: { xs: 'none', md: 'block' },
}}
/>The styled() Function — Reusable Styled Components
When you need a reusable styled component rather than one-off sx props, use styled() from @mui/material/styles. It has full access to the active theme.
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';
const PrimaryActionButton = styled(Button)(({ theme }) => ({
borderRadius: theme.shape.borderRadius * 3,
padding: theme.spacing(1.5, 4),
fontWeight: theme.typography.fontWeightBold,
textTransform: 'none',
'&:hover': {
backgroundColor: theme.palette.primary.dark,
},
}));
// Use it just like any other component
<PrimaryActionButton variant="contained">
Get Started
</PrimaryActionButton>You can also pass custom props through to the style function:
import Box from '@mui/material/Box';
const ColoredBox = styled(Box, {
shouldForwardProp: (prop) => prop !== 'highlight',
})(({ theme, highlight }) => ({
backgroundColor: highlight ? theme.palette.warning.light : 'transparent',
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadius,
}));
<ColoredBox highlight>This box is highlighted.</ColoredBox>shouldForwardProp prevents the custom prop from being forwarded to the DOM element (which would cause a React warning).
Custom Theming
Override colors, typography, spacing, and more with createTheme and ThemeProvider.
import { createTheme, ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
const theme = createTheme({
palette: {
mode: 'dark', // v5 syntax — v4 used palette.type
primary: {
main: '#6C63FF',
},
secondary: {
main: '#FF6584',
},
},
typography: {
fontFamily: '"Inter", "Roboto", sans-serif',
h1: {
fontSize: '2.5rem',
fontWeight: 700,
},
},
shape: {
borderRadius: 8,
},
});
function App() {
return (
<ThemeProvider theme={theme}>
<CssBaseline /> {/* Normalizes browser styles */}
<YourApp />
</ThemeProvider>
);
}Accessing the Theme in Components
import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';
function StatusBadge({ active }) {
const theme = useTheme();
return (
<Box
sx={{
display: 'inline-block',
px: 1.5,
py: 0.5,
borderRadius: '999px',
bgcolor: active
? theme.palette.success.light
: theme.palette.grey[300],
color: active
? theme.palette.success.contrastText
: theme.palette.text.secondary,
fontSize: theme.typography.caption.fontSize,
fontWeight: 600,
}}
>
{active ? 'Active' : 'Inactive'}
</Box>
);
}What Happened to makeStyles?
makeStyles from @material-ui/core/styles is a MUI v4 API built on JSS. It still exists in @mui/styles for v4 migration support, but that package is not compatible with React Strict Mode and is not maintained. The MUI team recommends migrating to sx or styled() instead.
If you're on an older codebase with makeStyles, you don't have to rewrite everything at once — but new components should use the v5 APIs.
When to Use Which
sxprop — quick one-off styles on any MUI component. Great for responsive layout and theme tokens.styled()— reusable styled components, complex selectors, prop-driven styles.createTheme— global design tokens (colors, typography, spacing, shape). Set it once at the app root.