Skip to content

Dark mode

MUI comes with two palette modes: light (the default) and dark.

You can make the theme dark by setting mode: 'dark'.

const darkTheme = createTheme({
  palette: {
    mode: 'dark',
  },
});

While it's only a single value change, the createTheme helper modifies several palette values. The colors modified by the palette mode are the following:

Typography

palette.text.primary

#fff

palette.text.secondary

rgba(255, 255, 255, 0.7)

palette.text.disabled

rgba(255, 255, 255, 0.5)

Buttons

palette.action.active

#fff

palette.action.hover

rgba(255, 255, 255, 0.08)

palette.action.selected

rgba(255, 255, 255, 0.16)

palette.action.disabled

rgba(255, 255, 255, 0.3)

palette.action.disabledBackground

rgba(255, 255, 255, 0.12)

Background

palette.background.default

#121212

palette.background.paper

#121212

Divider

palette.divider

rgba(255, 255, 255, 0.12)

Typography

palette.text.primary

rgba(0, 0, 0, 0.87)

palette.text.secondary

rgba(0, 0, 0, 0.6)

palette.text.disabled

rgba(0, 0, 0, 0.38)

Buttons

palette.action.active

rgba(0, 0, 0, 0.54)

palette.action.hover

rgba(0, 0, 0, 0.04)

palette.action.selected

rgba(0, 0, 0, 0.08)

palette.action.disabled

rgba(0, 0, 0, 0.26)

palette.action.disabledBackground

rgba(0, 0, 0, 0.12)

Background

palette.background.default

#fff

palette.background.paper

#fff

Divider

palette.divider

rgba(0, 0, 0, 0.12)

Note: The colors are modified only if you use the default palette. If you have a custom palette, you need to make sure that you have the correct values based on the mode. The following section explains how you can do it.

Dark mode with custom palette

The easiest way of how you can implement your custom palette that depends on mode is to have a dedicated function that will return the palette based on the mode. For example:

const getDesignTokens = (mode: PaletteMode) => ({
  palette: {
    mode,
    ...(mode === 'light'
      ? {
          // palette values for light mode
          primary: amber,
          divider: amber[200],
          text: {
            primary: grey[900],
            secondary: grey[800],
          },
        }
      : {
          // palette values for dark mode
          primary: deepOrange,
          divider: deepOrange[700],
          background: {
            default: deepOrange[900],
            paper: deepOrange[900],
          },
          text: {
            primary: '#fff',
            secondary: grey[500],
          },
        }),
  },
});

You can see on the example that there are different colors used based on whether the mode is light or dark. The next step is to use this function when creating the theme.

export default function App() {
  const [mode, setMode] = React.useState<PaletteMode>('light');
  const colorMode = React.useMemo(
    () => ({
      // The dark mode switch would invoke this method
      toggleColorMode: () => {
        setMode((prevMode: PaletteMode) =>
          prevMode === 'light' ? 'dark' : 'light',
        );
      },
    }),
    [],
  );

  // Update the theme only if the mode changes
  const theme = React.useMemo(() => createTheme(getDesignTokens(mode)), [mode]);

  return (
    <ColorModeContext.Provider value={colorMode}>
      <ThemeProvider theme={theme}>
        <Page />
      </ThemeProvider>
    </ColorModeContext.Provider>
  );
}

Here is a fully working example:

This is a dark mode theme with custom palette

Toggling color mode

You can use the React context to toggle the mode with a button inside your page.

light mode

System preference

Users might have specified a preference for a light or dark theme. The method by which the user expresses their preference can vary. It might be a system-wide setting exposed by the Operating System, or a setting controlled by the User Agent.

You can leverage this preference dynamically with the useMediaQuery hook and the prefers-color-scheme media query.

For instance, you can enable the dark mode automatically:

import * as React from 'react';
import useMediaQuery from '@mui/material/useMediaQuery';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';

function App() {
  const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');

  const theme = React.useMemo(
    () =>
      createTheme({
        palette: {
          mode: prefersDarkMode ? 'dark' : 'light',
        },
      }),
    [prefersDarkMode],
  );

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Routes />
    </ThemeProvider>
  );
}