Material UI: Customization
The sx Prop
The sx prop is the primary way to apply one-off styles in MUI. It supports theme tokens, responsive values, and pseudo-classes.
// sx uses theme values: spacing, palette, breakpoints
<Box
sx={{
p: 2, // padding: theme.spacing(2) = 16px
mt: 'auto', // marginTop: 'auto'
bgcolor: 'primary.main', // theme.palette.primary.main
color: 'primary.contrastText',
borderRadius: 2, // theme.shape.borderRadius * 2
boxShadow: 3, // theme.shadows[3]
// Responsive values
width: { xs: '100%', md: '50%' },
display: { xs: 'none', sm: 'block' },
// Pseudo-classes
'&:hover': { bgcolor: 'primary.dark' },
'&.Mui-disabled': { opacity: 0.5 },
// Nested selectors
'& .MuiButton-root': { textTransform: 'none' },
}}
>styled() API
import { styled } from '@mui/material/styles'
// Create a reusable styled component
const StyledCard = styled(Paper)(({ theme }) => ({
padding: theme.spacing(3),
borderRadius: theme.shape.borderRadius * 2,
transition: 'box-shadow 0.2s',
'&:hover': {
boxShadow: theme.shadows[8],
},
}))
// With props
const ColoredChip = styled(Chip, {
shouldForwardProp: prop => prop !== 'active',
})<{ active?: boolean }>(({ theme, active }) => ({
backgroundColor: active ? theme.palette.success.main : theme.palette.grey[300],
color: active ? theme.palette.success.contrastText : 'inherit',
}))Theme Component Overrides
// Override default styles for ALL instances of a component globally
const theme = createTheme({
components: {
MuiButton: {
defaultProps: {
disableElevation: true, // remove box-shadow from all contained buttons
variant: 'contained', // default variant
},
styleOverrides: {
root: {
textTransform: 'none', // remove ALL_CAPS on all buttons
borderRadius: 8,
},
containedPrimary: {
'&:hover': { backgroundColor: '#1565c0' }
}
}
},
MuiTextField: {
defaultProps: {
size: 'small',
variant: 'outlined',
}
},
MuiCssBaseline: {
styleOverrides: {
body: { scrollbarWidth: 'thin' }, // global CSS
}
}
}
})useTheme & useMediaQuery
import { useTheme, useMediaQuery } from '@mui/material'
function MyComponent() {
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down('md'))
return (
<Box sx={{ flexDirection: isMobile ? 'column' : 'row' }}>
<Typography color={theme.palette.primary.main}>
Current spacing: {theme.spacing(2)}
</Typography>
</Box>
)
}MUI v5 vs v6 vs Tailwind
MUI v5: Emotion-based, sx prop, theme system — current mainstream choice
MUI v6: Pigment CSS (build-time CSS-in-JS, zero runtime) — better performance, more Next.js compatible
MUI vs Tailwind: MUI wins for rapid prototyping with rich components; Tailwind wins for custom design systems and smaller bundle size
shadcn/ui + Tailwind: growing alternative — copy-paste components with full ownership, no library dependency
Joy UI: MUI's alternative design system (not Material Design) — more modern aesthetic
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free