CSS theme variables - Usage
Learn how to adopt CSS theme variables.
Getting started
The CSS variables API relies on a provider called CssVarsProvider
to inject styles into Material UI components.
CssVarsProvider
generates CSS variables out of all tokens in the theme that are serializable, and makes them available in the React context along with the theme itself via ThemeProvider
.
Once the App
renders on the screen, you will see the CSS theme variables in the HTML :root
stylesheet.
The variables are flattened and prefixed with --mui
by default:
import { CssVarsProvider } from '@mui/material/styles';
function App() {
return <CssVarsProvider>{/* ...you app */}</CssVarsProvider>;
}
Dark mode only application
To switch the default light to dark palette, set colorSchemes: { dark: true }
to the extendTheme
.
Material UI will generate the dark palette instead.
import { CssVarsProvider, extendTheme } from '@mui/material/styles';
const theme = extendTheme({
colorSchemes: { dark: true },
});
function App() {
return <CssVarsProvider theme={theme}>{/* ...you app */}</CssVarsProvider>;
}
Light and dark mode application
To support both light and dark modes, set colorSchemes: { light: true, dark: true }
to the extendTheme
.
Material UI will generate both light and dark palette with @media (prefers-color-scheme)
.
import { CssVarsProvider, extendTheme } from '@mui/material/styles';
const theme = extendTheme({
colorSchemes: { light: true, dark: true },
});
function App() {
return <CssVarsProvider theme={theme}>{/* ...you app */}</CssVarsProvider>;
}
If you want to manually toggle the color scheme, check out the advanced configuration.
Applying dark styles
To customize styles for dark mode, use theme.applyStyles
function.
This utility function will return the right selector.
The example below shows how to customize the Card component for dark mode:
import Card from '@mui/material/Card';
<Card
sx={(theme) => ({
backgroundColor: theme.vars.palette.background.default,
...theme.applyStyles('dark', {
boxShadow: 'none', // remove the box shadow in dark mode
}),
})}
/>;
Using theme variables
All of these variables are accessible in an object in the theme called vars
.
The structure of this object is a serializable theme structure with the values represent CSS variables.
theme.vars
(recommended): an object that refers to the CSS theme variables.const Button = styled('button')(({ theme }) => ({ backgroundColor: theme.vars.palette.primary.main, // var(--mui-palette-primary-main) color: theme.vars.palette.primary.contrastText, // var(--mui-palette-primary-contrastText) }));
For TypeScript, the typings are not enabled by default. Follow the TypeScript setup to enable the typings.
Native CSS: if you can't access the theme object, for example in a pure CSS file, you can use
var()
directly:/* external-scope.css */ .external-section { background-color: var(--mui-palette-grey-50); }
Theming
The major difference from the createTheme
approach is in palette customization.
With the extendTheme
API, you can specify the palette for light
and dark
color schemes at once. The rest of the theme structure remains the same.
Here are examples of customizing each part of the theme:
import { pink } from '@mui/material/colors';
extendTheme({
colorSchemes: {
light: {
palette: {
primary: {
main: pink[600],
},
},
},
dark: {
palette: {
primary: {
main: pink[400],
},
},
},
},
});
Channel tokens
A channel token is used for creating translucent color. It is a variable that consists of color space channels but without the alpha component. The value of a channel token is separated by a space, for example 12 223 31
, which can be combined with the color functions to create a translucent color.
The extendTheme()
automatically generates channel tokens that are likely to be used frequently from the theme palette. Those colors are suffixed with Channel
, for example:
const theme = extendTheme();
const light = theme.colorSchemes.light;
console.log(light.palette.primary.mainChannel); // '25 118 210'
// This token is generated from `theme.colorSchemes.light.palette.primary.main`.
You can use the channel tokens to create a translucent color like this:
const theme = extendTheme({
components: {
MuiChip: {
styleOverrides: {
root: ({ theme }) => ({
variants: [
{
props: { variant: 'outlined', color: 'primary' },
style: {
backgroundColor: `rgba(${theme.vars.palette.primary.mainChannel} / 0.12)`,
},
},
],
}),
},
},
},
});
Adding new theme tokens
You can add other key-value pairs to the theme input which will be generated as a part of the CSS theme variables:
const theme = extendTheme({
colorSchemes: {
light: {
palette: {
// The best part is that you can refer to the variables wherever you like 🤩
gradient:
'linear-gradient(to left, var(--mui-palette-primary-main), var(--mui-palette-primary-dark))',
border: {
subtle: 'var(--mui-palette-neutral-200)',
},
},
},
dark: {
palette: {
gradient:
'linear-gradient(to left, var(--mui-palette-primary-light), var(--mui-palette-primary-main))',
border: {
subtle: 'var(--mui-palette-neutral-600)',
},
},
},
},
});
function App() {
return <CssVarsProvider theme={theme}>...</CssVarsProvider>;
}
Then, you can access those variables from the theme.vars
object:
const Divider = styled('hr')(({ theme }) => ({
height: 1,
border: '1px solid',
borderColor: theme.vars.palette.border.subtle,
backgroundColor: theme.vars.palette.gradient,
}));
Or use var()
to refer to the CSS variable directly:
/* global.css */
.external-section {
background-color: var(--mui-palette-gradient);
}
For TypeScript, you need to augment the palette interfaces.
TypeScript
The theme variables type is not enabled by default. You need to import the module augmentation to enable the typings:
// The import can be in any file that is included in your `tsconfig.json`
import type {} from '@mui/material/themeCssVarsAugmentation';
import { styled } from '@mui/material/styles';
const StyledComponent = styled('button')(({ theme }) => ({
// ✅ typed-safe
color: theme.vars.palette.primary.main,
}));
Palette interfaces
To add new tokens to the theme palette, you need to augment the PaletteOptions
and Palette
interfaces:
declare module '@mui/material/styles' {
interface PaletteOptions {
gradient: string;
border: {
subtle: string;
};
}
interface Palette {
gradient: string;
border: {
subtle: string;
};
}
}
Next steps
If you need to support system preference and manual selection, check out the advanced configuration