Material UI Cheat Sheet
Covers installing MUI, theming with ThemeProvider, the sx prop, responsive breakpoints, and commonly used React components.
Installation & Theming
Setting up MUI and a custom ThemeProvider.
// npm install @mui/material @emotion/react @emotion/styledimport { createTheme, ThemeProvider } from '@mui/material/styles';import CssBaseline from '@mui/material/CssBaseline';const theme = createTheme({ palette: { mode: 'light', primary: { main: '#1976d2' }, }, typography: { fontFamily: 'Roboto, sans-serif', },});function App({ children }) { return ( <ThemeProvider theme={theme}> <CssBaseline /> {/* normalizes browser default styles */} {children} </ThemeProvider> );}
The sx Prop
Inline, theme-aware styling shorthand.
import Box from '@mui/material/Box';<Box sx={{ display: 'flex', p: 2, // padding: theme.spacing(2) m: { xs: 1, md: 3 }, // responsive margin per breakpoint bgcolor: 'primary.main', borderRadius: 1, '&:hover': { opacity: 0.8 }, // pseudo-class selector }}> Content</Box>
Common Components
Layout, form, and navigation building blocks.
import { Button, TextField, Grid, AppBar, Toolbar, Typography } from '@mui/material';function Form() { return ( <> <AppBar position="static"> <Toolbar> <Typography variant="h6">My App</Typography> </Toolbar> </AppBar> <Grid container spacing={2}> <Grid item xs={12} sm={6}> <TextField label="Name" fullWidth variant="outlined" /> </Grid> <Grid item xs={12} sm={6}> <Button variant="contained" color="primary" type="submit"> Submit </Button> </Grid> </Grid> </> );}
MUI System & Breakpoints
Theme utilities for responsive design.
- theme.breakpoints.up('md')- targets viewports at or above the md breakpoint (900px by default)
- useTheme()- hook that returns the active theme object inside a component
- useMediaQuery(theme.breakpoints.down('sm'))- hook returning a boolean for JS-level responsive logic
- styled(Component)- creates a styled component with full access to the theme
- theme.spacing(n)- converts a spacing unit (8px by default) into a pixel/rem value
- Stack- flexbox layout helper with direction and spacing props for evenly gapped children
Extending Theme Variants & Component Overrides
Registering brand-new variant options on existing components via theme.components, with full TypeScript augmentation.
// theme.tsimport { createTheme } from '@mui/material/styles';declare module '@mui/material/Button' { interface ButtonPropsVariantOverrides { gradient: true; }}const theme = createTheme({ components: { MuiButton: { styleOverrides: { root: { textTransform: 'none', borderRadius: 8 }, }, variants: [ { props: { variant: 'gradient' }, style: { background: 'linear-gradient(45deg, #1976d2, #21cbf3)', color: '#fff', }, }, ], defaultProps: { disableElevation: true }, }, },});// usage: <Button variant="gradient">Get Started</Button>
styled() API & CSS Variables Theme
Building reusable styled primitives and opting into MUI's cssVariables mode to avoid SSR flash-of-unstyled-theme.
import { styled } from '@mui/material/styles';import { experimental_extendTheme as extendTheme, Experimental_CssVarsProvider as CssVarsProvider } from '@mui/material/styles';const StyledCard = styled('div', { shouldForwardProp: (prop) => prop !== 'elevated',})<{ elevated?: boolean }>(({ theme, elevated }) => ({ padding: theme.spacing(3), borderRadius: theme.shape.borderRadius, boxShadow: elevated ? theme.shadows[4] : 'none', transition: theme.transitions.create(['box-shadow']),}));const cssVarsTheme = extendTheme({ colorSchemes: { light: true, dark: true },});function App({ children }) { return <CssVarsProvider theme={cssVarsTheme} defaultMode="system">{children}</CssVarsProvider>;}
Controlled Autocomplete with Async Options
A common real-world pattern: debounced remote search feeding a controlled Autocomplete.
import { useState, useMemo } from 'react';import Autocomplete from '@mui/material/Autocomplete';import TextField from '@mui/material/TextField';import CircularProgress from '@mui/material/CircularProgress';import { debounce } from '@mui/material/utils';function UserSearch() { const [options, setOptions] = useState([]); const [loading, setLoading] = useState(false); const fetchOptions = useMemo( () => debounce(async (query, cb) => { setLoading(true); const res = await fetch(`/api/users?q=${query}`); cb(await res.json()); setLoading(false); }, 300), [] ); return ( <Autocomplete options={options} loading={loading} getOptionLabel={(o) => o.name} isOptionEqualToValue={(o, v) => o.id === v.id} onInputChange={(_, value) => fetchOptions(value, setOptions)} renderInput={(params) => ( <TextField {...params} label="Search users" InputProps={{ ...params.InputProps, endAdornment: loading ? <CircularProgress size={16} /> : params.InputProps.endAdornment, }} /> )} /> );}
Performance, Bundle Size & Accessibility
Practices that matter once an MUI app grows past a prototype.
- Named imports only- import { Button } from '@mui/material' is tree-shaken by most bundlers; deep imports (@mui/material/Button) guarantee it but add import churn
- sx vs styled() at scale- sx is convenient but recomputes emotion styles per render; hoist truly static styles into styled() components on hot paths
- Virtualization- pair Autocomplete/Table with react-window for large option/row lists; MUI does not virtualize by default
- Modal/Popper focus trap- Dialog and Modal trap focus and restore it on close automatically -- don't build custom overlays without replicating this for keyboard users
- disableRipple / reduced motion- respect prefers-reduced-motion by disabling ripple/transition effects globally via theme.components.MuiButtonBase.defaultProps
- Emotion cache with SSR- createCache() + CacheProvider is required to avoid class-name mismatch/flicker when server-rendering (Next.js App Router needs the official @mui/material-nextjs plugin)
Slots, slotProps & Component Composition
The v5.15+ pattern for customizing a component's internal sub-elements without wrapper divs.
import Slider from '@mui/material/Slider';import Tooltip from '@mui/material/Tooltip';<Slider defaultValue={30} slots={{ valueLabel: Tooltip }} slotProps={{ thumb: { className: 'custom-thumb' }, track: { style: { backgroundColor: 'green' } }, }}/>// polymorphic 'component' prop -- render as a different root element/componentimport ListItem from '@mui/material/ListItem';import { Link as RouterLink } from 'react-router-dom';<ListItem component={RouterLink} to="/profile" button> Profile</ListItem>
Prefer the sx prop or styled() over inline style objects: sx integrates with the theme (spacing, palette, breakpoints) and is optimized by the MUI babel plugin, unlike plain style objects which bypass theming entirely.