380 lines
12 KiB
Markdown
380 lines
12 KiB
Markdown
|
|
# Theming
|
|||
|
|
|
|||
|
|
<p class="description">Customize Material UI with your theme. You can change the colors, the typography and much more.</p>
|
|||
|
|
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
Material UI components adhere to the library's default theme out of the box.
|
|||
|
|
Use `ThemeProvider` to inject a custom theme into your application.
|
|||
|
|
|
|||
|
|
`ThemeProvider` relies on the [context feature of React](https://react.dev/learn/passing-data-deeply-with-context) to pass the theme down to the components, so you need to make sure that `ThemeProvider` is a parent of the components you are trying to customize.
|
|||
|
|
You can learn more about this in [the API section](#themeprovider).
|
|||
|
|
|
|||
|
|
## 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`](/material-ui/customization/palette/)
|
|||
|
|
- [`.typography`](/material-ui/customization/typography/)
|
|||
|
|
- [`.spacing`](/material-ui/customization/spacing/)
|
|||
|
|
- [`.breakpoints`](/material-ui/customization/breakpoints/)
|
|||
|
|
- [`.zIndex`](/material-ui/customization/z-index/)
|
|||
|
|
- [`.transitions`](/material-ui/customization/transitions/)
|
|||
|
|
- [`.components`](/material-ui/customization/theme-components/)
|
|||
|
|
|
|||
|
|
You can check out the [default theme section](/material-ui/customization/default-theme/) to view the default theme in full.
|
|||
|
|
|
|||
|
|
### Custom variables
|
|||
|
|
|
|||
|
|
When using Material UI's theme with [MUI System](/system/getting-started/) or [any other styling solution](/material-ui/integrations/interoperability/), it can be convenient to add additional variables to the theme so you can use them everywhere.
|
|||
|
|
For instance:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
const theme = createTheme({
|
|||
|
|
status: {
|
|||
|
|
danger: orange[500],
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
:::warning
|
|||
|
|
`vars` is an autogenerated field for [CSS theme variables](/material-ui/customization/css-theme-variables/overview/).
|
|||
|
|
It will throw an error if you try to pass a value to it:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
createTheme({
|
|||
|
|
vars: { ... }, // ❌ error
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
:::
|
|||
|
|
|
|||
|
|
### TypeScript
|
|||
|
|
|
|||
|
|
You have to use [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) to add new variables to the `Theme` and `ThemeOptions`.
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
declare module '@mui/material/styles' {
|
|||
|
|
interface Theme {
|
|||
|
|
status: {
|
|||
|
|
danger: string;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
// allow configuration using `createTheme()`
|
|||
|
|
interface ThemeOptions {
|
|||
|
|
status?: {
|
|||
|
|
danger?: string;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
{{"demo": "CustomStyles.js"}}
|
|||
|
|
|
|||
|
|
To add extra variables to the `theme.palette`, see [palette customization](/material-ui/customization/palette/).
|
|||
|
|
|
|||
|
|
## Theme builder
|
|||
|
|
|
|||
|
|
<video autoPlay muted loop width="320">
|
|||
|
|
<source src="/static/studies.mp4" type="video/mp4" >
|
|||
|
|
</video>
|
|||
|
|
|
|||
|
|
The community has built great tools to build a theme:
|
|||
|
|
|
|||
|
|
- [mui-theme-creator](https://zenoo.github.io/mui-theme-creator/): A tool to help design and customize themes for the Material UI component library. Includes basic site templates to show various components and how they are affected by the theme
|
|||
|
|
- [Material palette generator](https://m2.material.io/inline-tools/color/): The Material palette generator can be used to generate a palette for any color you input.
|
|||
|
|
|
|||
|
|
## Accessing the theme in a component
|
|||
|
|
|
|||
|
|
You can access the theme variables inside your functional React components using the `useTheme` hook:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
import { useTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
function DeepChild() {
|
|||
|
|
const theme = useTheme();
|
|||
|
|
return <span>{`spacing ${theme.spacing}`}</span>;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Nesting the theme
|
|||
|
|
|
|||
|
|
[You can nest](https://v6.mui.com/system/styles/advanced/#theme-nesting) multiple theme providers.
|
|||
|
|
|
|||
|
|
{{"demo": "ThemeNesting.js"}}
|
|||
|
|
|
|||
|
|
The inner theme will **override** the outer theme.
|
|||
|
|
You can extend the outer theme by providing a function:
|
|||
|
|
|
|||
|
|
{{"demo": "ThemeNestingExtend.js"}}
|
|||
|
|
|
|||
|
|
## CSS theme variables
|
|||
|
|
|
|||
|
|
To generate CSS variables from the theme, set `cssVariables` to `true` in the theme configuration and pass it to the `ThemeProvider`:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
const theme = createTheme({
|
|||
|
|
cssVariables: true,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
function App() {
|
|||
|
|
return <ThemeProvider theme={theme}>...</ThemeProvider>;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
This generates a global stylesheet with the CSS theme variables:
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
:root {
|
|||
|
|
--mui-palette-primary-main: #1976d2;
|
|||
|
|
/* ...other variables */
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
All components under the `ThemeProvider` will use those CSS theme variables instead of raw values.
|
|||
|
|
|
|||
|
|
```diff title="Button styles"
|
|||
|
|
- color: #1976d2;
|
|||
|
|
+ color: var(--mui-palette-primary-main);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
To learn more about this feature, see the [CSS theme variables guide](/material-ui/customization/css-theme-variables/overview/).
|
|||
|
|
|
|||
|
|
## API
|
|||
|
|
|
|||
|
|
### `createTheme(options, ...args) => theme`
|
|||
|
|
|
|||
|
|
Generate a theme base on the options received. Then, pass it as a prop to [`ThemeProvider`](#themeprovider).
|
|||
|
|
|
|||
|
|
#### Arguments
|
|||
|
|
|
|||
|
|
1. `options` (_object_): Takes an incomplete theme object and adds the missing parts.
|
|||
|
|
2. `...args` (_object[]_): Deep merge the arguments with the about to be returned theme.
|
|||
|
|
|
|||
|
|
:::warning
|
|||
|
|
Only the first argument (`options`) is processed by the `createTheme()` function.
|
|||
|
|
While passing multiple arguments currently works for backward compatibility, this behavior may be removed in future versions.
|
|||
|
|
To ensure your code remains forward-compatible, you should manually deep merge the theme objects and pass the result as a single object to `createTheme()`.
|
|||
|
|
:::
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { deepmerge } from '@mui/utils';
|
|||
|
|
import { createTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
const theme = createTheme(deepmerge(options1, options2));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Returns
|
|||
|
|
|
|||
|
|
`theme` (_object_): A complete, ready-to-use theme object.
|
|||
|
|
|
|||
|
|
#### Examples
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { createTheme } from '@mui/material/styles';
|
|||
|
|
import { green, purple } from '@mui/material/colors';
|
|||
|
|
|
|||
|
|
const theme = createTheme({
|
|||
|
|
palette: {
|
|||
|
|
primary: {
|
|||
|
|
main: purple[500],
|
|||
|
|
},
|
|||
|
|
secondary: {
|
|||
|
|
main: green[500],
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Theme composition: using theme options to define other options
|
|||
|
|
|
|||
|
|
When the value for a theme option is dependent on another theme option, you should compose the theme in steps.
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { createTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
let theme = createTheme({
|
|||
|
|
palette: {
|
|||
|
|
primary: {
|
|||
|
|
main: '#0052cc',
|
|||
|
|
},
|
|||
|
|
secondary: {
|
|||
|
|
main: '#edf2ff',
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
theme = createTheme(theme, {
|
|||
|
|
palette: {
|
|||
|
|
info: {
|
|||
|
|
main: theme.palette.secondary.main,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Think of creating a theme as a two-step composition process: first, you define the basic design options; then, you'll use these design options to compose other options.
|
|||
|
|
|
|||
|
|
**WARNING**: `theme.vars` is a private field used for CSS variables support. Please use another name for a custom object.
|
|||
|
|
|
|||
|
|
### Merging className and style props in defaultProps
|
|||
|
|
|
|||
|
|
By default, when a component has `defaultProps` defined in the theme, props passed to the component override the default props completely.
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
import { createTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
const theme = createTheme({
|
|||
|
|
components: {
|
|||
|
|
MuiButton: {
|
|||
|
|
defaultProps: {
|
|||
|
|
className: 'default-button-class',
|
|||
|
|
style: { marginTop: 8 },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// className will be: "custom-button-class" (default ignored)
|
|||
|
|
// style will be: { color: 'blue' } (default ignored)
|
|||
|
|
<Button className="custom-button-class" style={{ color: 'blue' }}>
|
|||
|
|
Click me
|
|||
|
|
</Button>;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
You can change this behavior by configuring the theme to merge `className` and `style` props instead of replacing them.
|
|||
|
|
|
|||
|
|
To do this, set `theme.components.mergeClassNameAndStyle` to `true`:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
import { createTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
const theme = createTheme({
|
|||
|
|
components: {
|
|||
|
|
mergeClassNameAndStyle: true,
|
|||
|
|
MuiButton: {
|
|||
|
|
defaultProps: {
|
|||
|
|
className: 'default-button-class',
|
|||
|
|
style: { marginTop: 8 },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Here's what the example above looks like with this configuration:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
// className will be: "default-button-class custom-button-class"
|
|||
|
|
// style will be: { marginTop: 8, color: 'blue' }
|
|||
|
|
<Button className="custom-button-class" style={{ color: 'blue' }}>
|
|||
|
|
Click me
|
|||
|
|
</Button>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### `responsiveFontSizes(theme, options) => theme`
|
|||
|
|
|
|||
|
|
Generate responsive typography settings based on the options received.
|
|||
|
|
|
|||
|
|
#### Arguments
|
|||
|
|
|
|||
|
|
1. `theme` (_object_): The theme object to enhance.
|
|||
|
|
2. `options` (_object_ [optional]):
|
|||
|
|
|
|||
|
|
- `breakpoints` (_array\<string\>_ [optional]): Default to `['sm', 'md', 'lg']`. Array of [breakpoints](/material-ui/customization/breakpoints/) (identifiers).
|
|||
|
|
- `disableAlign` (_bool_ [optional]): Default to `false`. Whether font sizes change slightly so line
|
|||
|
|
heights are preserved and align to Material Design's 4px line height grid.
|
|||
|
|
This requires a unitless line height in the theme's styles.
|
|||
|
|
- `factor` (_number_ [optional]): Default to `2`. This value determines the strength of font size resizing. The higher the value, the less difference there is between font sizes on small screens.
|
|||
|
|
The lower the value, the bigger font sizes for small screens. The value must be greater than 1.
|
|||
|
|
- `variants` (_array\<string\>_ [optional]): Default to all. The typography variants to handle.
|
|||
|
|
|
|||
|
|
#### Returns
|
|||
|
|
|
|||
|
|
`theme` (_object_): The new theme with a responsive typography.
|
|||
|
|
|
|||
|
|
#### Examples
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { createTheme, responsiveFontSizes } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
let theme = createTheme();
|
|||
|
|
theme = responsiveFontSizes(theme);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### `unstable_createMuiStrictModeTheme(options, ...args) => theme`
|
|||
|
|
|
|||
|
|
**WARNING**: Do not use this method in production.
|
|||
|
|
|
|||
|
|
Generates a theme that reduces the amount of warnings inside [`React.StrictMode`](https://react.dev/reference/react/StrictMode) like `Warning: findDOMNode is deprecated in StrictMode`.
|
|||
|
|
|
|||
|
|
#### Requirements
|
|||
|
|
|
|||
|
|
Currently `unstable_createMuiStrictModeTheme` adds no additional requirements.
|
|||
|
|
|
|||
|
|
#### Arguments
|
|||
|
|
|
|||
|
|
1. `options` (_object_): Takes an incomplete theme object and adds the missing parts.
|
|||
|
|
2. `...args` (_object[]_): Deep merge the arguments with the about to be returned theme.
|
|||
|
|
|
|||
|
|
#### Returns
|
|||
|
|
|
|||
|
|
`theme` (_object_): A complete, ready-to-use theme object.
|
|||
|
|
|
|||
|
|
#### Examples
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import { unstable_createMuiStrictModeTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
const theme = unstable_createMuiStrictModeTheme();
|
|||
|
|
|
|||
|
|
function App() {
|
|||
|
|
return (
|
|||
|
|
<React.StrictMode>
|
|||
|
|
<ThemeProvider theme={theme}>
|
|||
|
|
<LandingPage />
|
|||
|
|
</ThemeProvider>
|
|||
|
|
</React.StrictMode>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### `ThemeProvider`
|
|||
|
|
|
|||
|
|
This component takes a `theme` prop and applies it to the entire React tree that it is wrapping around.
|
|||
|
|
It should preferably be used at **the root of your component tree**.
|
|||
|
|
|
|||
|
|
#### Props
|
|||
|
|
|
|||
|
|
| Name | Type | Description |
|
|||
|
|
| :--------------- | :--------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|||
|
|
| children \* | node | Your component tree. |
|
|||
|
|
| theme \* | union: object | func | A theme object, usually the result of [`createTheme()`](#createtheme-options-args-theme). The provided theme will be merged with the default theme. You can provide a function to extend the outer theme. |
|
|||
|
|
|
|||
|
|
#### Examples
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
import * as React from 'react';
|
|||
|
|
import { red } from '@mui/material/colors';
|
|||
|
|
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
const theme = createTheme({
|
|||
|
|
palette: {
|
|||
|
|
primary: {
|
|||
|
|
main: red[500],
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
function App() {
|
|||
|
|
return <ThemeProvider theme={theme}>...</ThemeProvider>;
|
|||
|
|
}
|
|||
|
|
```
|