Change root background color with Material-UI theme

CssBaseline is the component that controls this aspect. If you aren't using CssBaseline, then you are just seeing the default provided by the browser.

Here is a working v4 example (v5 example further down):

import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "@material-ui/core/CssBaseline";
import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";

const themeLight = createMuiTheme({
  palette: {
    background: {
      default: "#e4f0e2"
    }
  }
});

const themeDark = createMuiTheme({
  palette: {
    background: {
      default: "#222222"
    },
    text: {
      primary: "#ffffff"
    }
  }
});

const App = () => {
  const [light, setLight] = React.useState(true);
  return (
    <MuiThemeProvider theme={light ? themeLight : themeDark}>
      <CssBaseline />
      <Button onClick={() => setLight(prev => !prev)}>Toggle Theme</Button>
    </MuiThemeProvider>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit theme body background


Below is a Material-UI v5 example. The only difference from v4 is the name change for ThemeProvider (though this name is also available in v4 in addition to MuiThemeProvider) and createTheme (instead of createMuiTheme) and using the new @mui/material package name instead of @material-ui/core.

import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import Button from "@mui/material/Button";

const themeLight = createTheme({
  palette: {
    background: {
      default: "#e4f0e2"
    }
  }
});

const themeDark = createTheme({
  palette: {
    background: {
      default: "#222222"
    },
    text: {
      primary: "#ffffff"
    }
  }
});

const App = () => {
  const [light, setLight] = React.useState(true);
  return (
    <ThemeProvider theme={light ? themeLight : themeDark}>
      <CssBaseline />
      <Button onClick={() => setLight((prev) => !prev)}>Toggle Theme</Button>
    </ThemeProvider>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit theme body background


On top of @NearHuscarl 's answer, importing the GlobalStyles after the CSSBaseLine, will retain the page defaults (like margin: 0, etc.,) still able to customize root-level / global styles. For eg,

import { Component } from "react";
import { Button, CssBaseline, GlobalStyles } from "@mui/material";
import { ThemeProvider, createTheme } from "@mui/material/styles";

export class App extends Component {
  render() {
    const theme = createTheme({
      palette: {
        mode: "dark",
        primary: {
          main: "#ff0000",
          contrastText: "#fff",
        },
        secondary: {
          main: green[500],
        },
      },
    });
    return (
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <GlobalStyles
          styles={{
            body: { backgroundColor: "cyan" },
          }}
        />
        <Button color="primary" variant="contained">
          Button
        </Button>
      </ThemeProvider>
    );
  }
}

export default App;

(I'm just using class component out of habit 😅)

Full example with nested themes MUI Theme toggle