reactjsmantine

How to change body bg color for light and dark mode Mantine UI


How do I customize mantine background colors for body in theme object? I am trying to achieve something like this

const theme = createTheme({
  colors: {
    // Light mode colors
    light: {
      body: '#ffffff', // Light mode body color
      // Define other light mode colors here
    },
    // Dark mode colors
    dark: {
      body: '#000000', // Dark mode body color
      // Define other dark mode colors here
    },
  },
});

Solution

  • You should use light/dark scheme data-* attributes on the html or pseudo :root element somewhere in your CSS:

    /* For light mode */
    :root[data-mantine-color-scheme="light"] {
      --mantine-color-body: var(--mantine-color-gray-1) !important;
    }
    
    /* For dark mode */
    :root[data-mantine-color-scheme="dark"] {
      --mantine-color-body: #282827 !important;
    }
    

    Read on to understand why !important is required.


    There are two things to keep in mind when changing the background-color with Mantine:

    Let's talk about the first part. This is a bit tricky to get it right. The background-color is set on the body tag using --mantine-color-body CSS variable. As per the documentation the value of this CSS variable is fixed #FFFFFF in light scheme and --mantine-color-dark-7 variable in dark scheme. While correct for dark scheme, that's not exactly true for light scheme:

    If custom theme is not used by passing it to the <MantineProvider /> then, the default value of --mantine-color-body is as follows assuming you are importing Mantine's style.css in your code somewhere:

    /* As defined in @mantine/core/styles.css or @mantine/core/styles.layer.css */
    :root[data-mantine-color-scheme='dark'] {
      --mantine-color-body: var(--mantine-color-dark-7);
    }
    
    :root[data-mantine-color-scheme='light'] {
      --mantine-color-body: var(--mantine-color-white);
    }
    
    body {
      background-color: var(--mantine-color-body);
    }
    

    The value of the --mantine-color-body is overridden in light mode if you pass a custom Theme to the <MantineProvider /> which includes the white field as follows:

    import { DEFAULT_THEME, createTheme, mergeMantineTheme } from '@mantine/core';
    
    const overrides = createTheme({
      // Set this color to `--mantine-color-body` CSS variable
      white: '#F0F0F0',
      colors: {
        // ...
      },
    });
    
    const theme = mergeMantineTheme(DEFAULT_THEME, overrides);
    
    
    function withMantine(App) {
      return (
        <MantineProvider theme={theme}>
          <App />
        </MantineProvider>
      );
    },
    

    However changing the value of theme.white to anything other than #FFFFFF or some close shade of pure white color is seldom a good idea. The variable --mantine-color-white is used at multiple places while keeping accessibility in mind. So, it makes sense to change the value of --mantine-color-body variable than changing the --mantine-color-white variable.

    Now, the second part is where to modify it. Mantine documents the data-* attributes it sets for color-scheme as part of MantineProvider mounting. So, those should be used in the CSS to set this up.

    One small gotcha here is that <MantineProvider /> dynamically injects the styles (containing all the CSS variables as per theme) in the document's <head> section and it gets added when the application is being rendered. It means that by this time, your custom imported CSS will be already added and these dynamically added styles will be later in the document causing the main imported CSS to be overridden. And, that is why you need to use !important specifier as shown earlier. One other option would be to simply set these two variables on body tag instead of :root by adding more specificity to the selector:

    /* For light mode */
    :root[data-mantine-color-scheme="light"] body {
      --mantine-color-body: var(--mantine-color-gray-1);
    }
    
    /* For dark mode */
    :root[data-mantine-color-scheme="dark"] body {
      --mantine-color-body: #282827;
    }