Themes

Themes

Customize Material-UI with our theme. You can change the colors, the typography and much more.

The theme specifies the color of the components, darkness of the surfaces, level of shadow, appropriate opacity of ink elements, etc.

Themes let you apply a consistent tone to your app. It allows you to customize all design aspects of your project in order to meet the specific needs of your business or brand.

To promote greater consistency between apps, light and dark theme types are available to choose from. By default, components use the light theme type.

Theme provider

If you wish to customize the theme, you need to use the MuiThemeProvider component in order to inject a theme into your application. However, this is optional; Material-UI components come with a default theme.

MuiThemeProvider relies on the context feature of React to pass the theme down to the components, so you need to make sure that MuiThemeProvider is a parent of the components you are trying to customize. You can learn more about this in the API section.

Theme configuration variables

Changing the theme configuration variables is the most effective way to match Material-UI to your needs. The following sections cover the most important theme variables:

Palette

Intentions

A color intention is a mapping of a palette to a given intention within your application.

The theme exposes the following color intentions:

  • primary - used to represent primary interface elements for a user.
  • secondary - used to represent secondary interface elements for a user.
  • error - used to represent interface elements that the user should be made aware of.

The default palette uses the shades prefixed with A (A200, etc.) for the secondary intention, and the un-prefixed shades for the other intentions.

If you want to learn more about color, you can check out the color section.

Custom palette

You may override the default palette values by including a palette object as part of your theme.

If any of the palette.primary, palette.secondary or palette.error 'intention' objects are provided, they will replace the defaults.

The intention value can either be a color object, or an object with one or more of the following keys:

interface PaletteIntention {
  light?: string;
  main: string;
  dark?: string;
  contrastText?: string;
};

Using a color object

The simplest way to customize an intention is to import one or more of the provided colors and apply them to a palette intention:

import { createMuiTheme } from '@material-ui/core/styles';
import blue from '@material-ui/core/colors/blue';

const theme = createMuiTheme({
  palette: {
    primary: blue,
  },
});

If the intention key receives a color object as in the example above, the following mapping is used to populate the required keys:

palette: {
  primary: {
    light: palette.primary[300],
    main: palette.primary[500],
    dark: palette.primary[700],
    contrastText: getContrastText(palette.primary[500]),
  },
  secondary: {
    light: palette.secondary.A200,
    main: palette.secondary.A400,
    dark: palette.secondary.A700,
    contrastText: getContrastText(palette.secondary.A400),
  },
  error: {
    light: palette.error[300],
    main: palette.error[500],
    dark: palette.error[700],
    contrastText: getContrastText(palette.error[500]),
  },
},

This example illustrates how you could recreate the default palette values:

import { createMuiTheme } from '@material-ui/core/styles';
import indigo from '@material-ui/core/colors/indigo';
import pink from '@material-ui/core/colors/pink';
import red from '@material-ui/core/colors/red';

// All the following keys are optional.
// We try our best to provide a great default value.
const theme = createMuiTheme({
  palette: {
    primary: indigo,
    secondary: pink,
    error: red,
    // Used by `getContrastText()` to maximize the contrast between the background and
    // the text.
    contrastThreshold: 3,
    // Used to shift a color's luminance by approximately
    // two indexes within its tonal palette.
    // E.g., shift from Red 500 to Red 300 or Red 700.
    tonalOffset: 0.2,
  },
});

Providing the colors directly

If you wish to provide more customized colors, you can either create your own color object, or directly supply colors to some or all of the intention's keys:

import { createMuiTheme } from '@material-ui/core/styles';

const theme = createMuiTheme({
  palette: {
    primary: {
      // light: will be calculated from palette.primary.main,
      main: '#ff4400',
      // dark: will be calculated from palette.primary.main,
      // contrastText: will be calculated to contrast with palette.primary.main
    },
    secondary: {
      light: '#0066ff',
      main: '#0044ff',
      // dark: will be calculated from palette.secondary.main,
      contrastText: '#ffcc00',
    },
    // error: will use the default color
  },
});

As in the example above, if the intention object contains custom colors using any of the main, light, dark or contrastText keys, these map as follows:

  • If the dark and / or light keys are omitted, their value(s) will be calculated from main, according to the tonalOffset value.

  • If contrastText is omitted, its value will be calculated to contrast with main, according to thecontrastThreshold value.

Both the tonalOffset and contrastThreshold values may be customized as needed. A higher value for tonalOffset will make calculated values for light lighter, and dark darker. A higher value for contrastThreshold increases the point at which a background color is considered light, and given a dark contrastText.

Note that contrastThreshold follows a non-linear curve.

Example

Color tool

Need inspiration? The Material Design team has built an awesome palette configuration tool to help you.

Type (light /dark theme)

You can make the theme dark by setting type to dark. While it's only a single property value change, internally it modifies the value of the following keys:

  • palette.text
  • palette.divider
  • palette.background
  • palette.action
const theme = createMuiTheme({
  palette: {
    type: 'dark',
  },
});

Primary color #3f51b5

Primary text #fff

Typography

Too many type sizes and styles at once can spoil any layout. The theme provides a limited set of type sizes that work well together along with the layout grid. These sizes are used across the components.

Have a look at the following example regarding changing the default values, such as the font family. If you want to learn more about typography, you can check out the typography section.

body1

subheading

body1

subheading

Typography - Font family

const theme = createMuiTheme({
  typography: {
    // Use the system font instead of the default Roboto font.
    fontFamily: [
      '-apple-system',
      'BlinkMacSystemFont',
      '"Segoe UI"',
      'Roboto',
      '"Helvetica Neue"',
      'Arial',
      'sans-serif',
      '"Apple Color Emoji"',
      '"Segoe UI Emoji"',
      '"Segoe UI Symbol"',
    ].join(','),
  },
});

Typography - Font size

Material-UI uses rem units for the font size. The browser <html> element default font size is 16px, but browsers have an option to change this value, so rem units allow us to accommodate the user's settings, resulting in a much better user experience. Users change font size settings for all kinds of reasons, from poor eyesight to choosing optimum settings for devices that can be vastly different in size and viewing distance.

To change the font-size of Material-UI you can provide a fontSize property. The default value is 14px.

const theme = createMuiTheme({
  typography: {
    // In Japanese the characters are usually larger.
    fontSize: 12,
  },
});

The computed font size by the browser follows this mathematical equation:

font-size

Typography - HTML font size

You might want to change the <html> element default font size. For instance, when using the 10px simplification. We provide a htmlFontSize theme property for this use case. It's telling Material-UI what's the font-size on the <html> element is. It's used to adjust the rem value so the calculated font-size always match the specification.

const theme = createMuiTheme({
  typography: {
    // Tell Material-UI what's the font-size on the html element is.
    htmlFontSize: 10,
  },
});
html {
  font-size: 62.5%; /* 62.5% of 16px = 10px */
}

You need to apply the above CSS on the html element of this page to see the below demo rendered correctly

body1

Other variables

In addition to the palette, dark and light types, and typography, the theme normalizes implementation by providing many more default values, such as breakpoints, shadows, transitions, etc. You can check out the default theme section to view the default theme in full.

Custom variables

When using Material-UI's styling solution with your own components, you can also take advantage of the theme. It can be convenient to add additional variables to the theme so you can use them everywhere. For instance:

Customizing all instances of a component type

CSS

When the configuration variables aren't powerful enough, you can take advantage of the overrides key of the theme to potentially change every single style injected by Material-UI into the DOM. That's a really powerful feature.

const theme = createMuiTheme({
  overrides: {
    MuiButton: { // Name of the component ⚛️ / style sheet
      root: { // Name of the rule
        color: 'white', // Some CSS
      },
    },
  },
});

The list of these customization points for each component is documented under the Component API section. For instance, you can have a look at the Button. Alternatively, you can always have a look at the implementation.

Properties

You can also apply properties on all the instances of a component type. We expose a props key in the theme for this use case.

const theme = createMuiTheme({
  props: {
    // Name of the component ⚛️
    MuiButtonBase: {
      // The properties to apply
      disableRipple: true, // No more ripple, on the whole application 💣!
    },
  },
});

Accessing the theme in a component

You might need to access the theme variables inside your React components. Let's say you want to display the value of the primary color, you can use the withTheme() higher-order component to do so. Here is an example:

Primary color #2196f3

Primary text rgba(0, 0, 0, 0.87)

Nesting the theme

The theming solution is very flexible, as you can nest multiple theme providers. This can be really useful when dealing with different area of your application that have distinct appearance from each other.

A note on performance

The performance implications of nesting the MuiThemeProvider component are linked to JSS's work behind the scenes. The main point to understand is that we cache the injected CSS with the following tuple (styles, theme).

  • theme: If you provide a new theme at each render, a new CSS object will be computed and injected. Both for UI consistency and performance, it's better to render a limited number of theme objects.
  • styles: The larger the styles object is, the more work is needed.

API

MuiThemeProvider

This component takes a theme property, and makes the theme available down the React tree thanks to React context. It should preferably be used at the root of your component tree.

You can see the full properties API in this dedicated page.

Examples

import React from 'react';
import { render } from 'react-dom';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import Root from './Root';

const theme = createMuiTheme();

function App() {
  return (
    <MuiThemeProvider theme={theme}>
      <Root />
    </MuiThemeProvider>
  );
}

render(<App />, document.querySelector('#app'));

createMuiTheme(options) => theme

Generate a theme base on the options received.

Arguments

  1. options (Object): Takes an incomplete theme object and adds the missing parts.

Returns

theme (Object): A complete, ready to use theme object.

Examples

import { createMuiTheme } from '@material-ui/core/styles';
import purple from '@material-ui/core/colors/purple';
import green from '@material-ui/core/colors/green';

const theme = createMuiTheme({
  palette: {
    primary: purple,
    secondary: green,
  },
  status: {
    danger: 'orange',
  },
});

withTheme()(Component) => Component

Provide the theme object as a property of the input component so it can be used in the render method.

Arguments

  1. Component: The component that will be wrapped.

Returns

Component: The new component created.

Examples

import { withTheme } from '@material-ui/core/styles';

function MyComponent(props) {
  return <div>{props.theme.direction}</div>;
}

export default withTheme()(MyComponent);