docs/data/material/migration/migration-v4/v5-style-changes.md
Material UI v5 introduces a number of breaking changes from v4. Many of these changes can be resolved automatically using the codemods described in the main migration guide.
The following document lists all breaking changes related to styles and themes in v5 and how to address them.
After you're finished here, please move on to Breaking changes in v5 part two: components to continue the migration process.
:::warning Breaking changes that are handled by codemods are denoted by a ✅ emoji in the table of contents on the right side of the screen.
If you have already followed the instructions in the main migration guide and run the codemods, then you should not need to take any further action on these items.
All other changes must be handled manually. :::
Although your style overrides defined in the theme may partially work, there is an important difference regarding how the nested elements are styled.
The $ syntax (local rule reference) used with JSS will not work with Emotion.
You need to replace those selectors with a valid class selector.
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
- '&$focused': {
+ '&.Mui-focused': {
borderWidth: 1,
}
}
}
}
}
});
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
- '& $notchedOutline': {
+ '& .MuiOutlinedInput-notchedOutline': {
borderWidth: 1,
}
}
}
}
}
});
:::info
For each component, we export a [component]Classes constant that contains all nested classes for that component.
You can rely on this instead of hardcoding the classes. :::
+import { outlinedInputClasses } from '@mui/material/OutlinedInput';
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
- '& $notchedOutline': {
+ [`& .${outlinedInputClasses.notchedOutline}`]: {
borderWidth: 1,
}
}
}
}
}
});
Take a look at the complete list of global state classnames available.
The alternative, array-based syntax JSS supports for space- and comma-separated values is not supported by Emotion.
Before
const theme = createTheme({
overrides: {
MuiBox: {
root: {
background: [
['url(image1.png)', 'no-repeat', 'top'],
['url(image2.png)', 'no-repeat', 'center'],
'!important',
],
},
},
},
});
After
const theme = createTheme({
components: {
MuiBox: {
styleOverrides: {
root: {
background:
'url(image1.png) no-repeat top, url(image2.png) no-repeat center !important',
},
},
},
},
});
Be sure to add units to numeric values as appropriate.
Before
const theme = createTheme({
overrides: {
MuiOutlinedInput: {
root: {
padding: [[5, 8, 6]],
},
},
},
});
After
const theme = createTheme({
components: {
MuiOutlinedInput: {
styleOverrides: {
root: {
padding: '5px 8px 6px',
},
},
},
},
});
Support for non-ref-forwarding class components in the component prop or as immediate children has been dropped.
If you were using unstable_createStrictModeTheme or didn't see any warnings related to findDOMNode in React.StrictMode then you don't need to take any further action.
Otherwise check out the Caveat with refs section in the Composition guide to find out how to migrate.
This change affects almost all components where you're using the component prop or passing children to components that require children to be elements (for example <MenuList><CustomMenuItem /></MenuList>).
For some components, you may get a type error when passing ref.
To avoid the error, you should use a specific element type.
For example, Card expects the type of ref to be HTMLDivElement, and ListItem expects its ref type to be HTMLLIElement.
Here is an example:
import * as React from 'react';
import Card from '@mui/material/Card';
import ListItem from '@mui/material/ListItem';
export default function SpecificRefType() {
- const cardRef = React.useRef<HTMLElement>(null);
+ const cardRef = React.useRef<HTMLDivElement>(null);
- const listItemRef = React.useRef<HTMLElement>(null);
+ const listItemRef = React.useRef<HTMLLIElement>(null);
return (
<div>
<Card ref={cardRef}></Card>
<ListItem ref={listItemRef}></ListItem>
</div>
);
}
Here are the specific element types that each component expects:
HTMLDivElementHTMLDivElementHTMLDivElementHTMLDivElementHTMLDivElementHTMLDivElementHTMLUListElementHTMLUListElementHTMLDivElementHTMLDivElementHTMLButtonElementHTMLUListElementThe style library used by default in v5 is Emotion.
If you were using JSS for the style overrides of Material UI components—for example, those created by makeStyles—you will need to take care of the CSS injection order.
JSS <style>' elements need to be injected in the <head> after Emotion <style>' elements.
To do so, you need to have the StyledEngineProvider with the injectFirst option at the top of your component tree, as shown here:
import * as React from 'react';
import { StyledEngineProvider } from '@mui/material/styles';
export default function GlobalCssPriority() {
return (
<StyledEngineProvider injectFirst>
</StyledEngineProvider>
);
}
If you have a custom cache and are using Emotion to style your app, it will override the cache provided by Material UI.
To correct the injection order, add the prepend option to createCache, as shown below:
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const cache = createCache({
key: 'css',
+ prepend: true,
});
export default function PlainCssPriority() {
return (
<CacheProvider value={cache}>
</CacheProvider>
);
}
:::warning
If you are using styled-components and have a StyleSheetManager with a custom target, make sure that the target is the first element in the HTML <head>.
To see how it can be done, take a look at the StyledEngineProvider implementation in the @mui/styled-engine-sc package.
:::
The structure of the theme has changed in v5. You need to update its shape.
For a smoother transition, the adaptV4Theme helper allows you to iteratively upgrade some of the theme changes to the new theme structure.
-import { createMuiTheme } from '@mui/material/styles';
+import { createTheme, adaptV4Theme } from '@mui/material/styles';
-const theme = createMuiTheme({
+const theme = createTheme(adaptV4Theme({
// v4 theme
-});
+}));
:::warning
This adapter only handles the input arguments of createTheme().
If you modify the shape of the theme after its creation, you need to migrate the structure manually.
:::
The following changes are supported by the adapter:
The "gutters" abstraction hasn't proven to be used frequently enough to be valuable.
-theme.mixins.gutters(),
+paddingLeft: theme.spacing(2),
+paddingRight: theme.spacing(2),
+[theme.breakpoints.up('sm')]: {
+ paddingLeft: theme.spacing(3),
+ paddingRight: theme.spacing(3),
+},
theme.spacing now returns single values with px units by default.
This change improves the integration with styled-components & Emotion.
Before:
theme.spacing(2) => 16
After:
theme.spacing(2) => '16px'
The theme.palette.type key was renamed to theme.palette.mode, to better follow the "dark mode" terminology that is usually used for describing this feature.
import { createTheme } from '@mui/material/styles';
-const theme = createTheme({ palette: { type: 'dark' } }),
+const theme = createTheme({ palette: { mode: 'dark' } }),
The default theme.palette.info colors were changed to pass the AA accessibility standard contrast ratio in both light and dark modes.
info = {
- main: cyan[500],
+ main: lightBlue[700], // lightBlue[400] in "dark" mode
- light: cyan[300],
+ light: lightBlue[500], // lightBlue[300] in "dark" mode
- dark: cyan[700],
+ dark: lightBlue[900], // lightBlue[700] in "dark" mode
}
The default theme.palette.success colors were changed to pass the AA accessibility standard contrast ratio in both light and dark modes.
success = {
- main: green[500],
+ main: green[800], // green[400] in "dark" mode
- light: green[300],
+ light: green[500], // green[300] in "dark" mode
- dark: green[700],
+ dark: green[900], // green[700] in "dark" mode
}
The default theme.palette.warning colors were changed to pass the AA accessibility standard contrast ratio in both light and dark modes.
warning = {
- main: orange[500],
+ main: '#ED6C02', // orange[400] in "dark" mode
- light: orange[300],
+ light: orange[500], // orange[300] in "dark" mode
- dark: orange[700],
+ dark: orange[900], // orange[700] in "dark" mode
}
The theme.palette.text.hint key was unused in Material UI components, and has been removed.
If you depend on it, you can add it back:
import { createTheme } from '@mui/material/styles';
-const theme = createTheme(),
+const theme = createTheme({
+ palette: { text: { hint: 'rgba(0, 0, 0, 0.38)' } },
+});
The component definitions in the theme were restructured under the components key to make them easier to find.
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
- props: {
- MuiButton: {
- disableRipple: true,
- },
- },
+ components: {
+ MuiButton: {
+ defaultProps: {
+ disableRipple: true,
+ },
+ },
+ },
});
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
- overrides: {
- MuiButton: {
- root: { padding: 0 },
- },
- },
+ components: {
+ MuiButton: {
+ styleOverrides: {
+ root: { padding: 0 },
+ },
+ },
+ },
});
If you are using the utilities from @mui/styles together with the @mui/material, you should replace the use of ThemeProvider from @mui/styles with the one exported from @mui/material/styles.
This way, the theme provided in the context will be available in both the styling utilities exported from @mui/styles, like makeStyles, withStyles, etc., along with the Material UI components.
-import { ThemeProvider } from '@mui/styles';
+import { ThemeProvider } from '@mui/material/styles';
Make sure to add a ThemeProvider at the root of your application, as the defaultTheme is no longer available in the utilities coming from @mui/styles.
The @mui/styles package is no longer part of @mui/material/styles.
If you are using @mui/styles together with @mui/material you need to add a module augmentation for the DefaultTheme.
// in the file where you are creating the theme (invoking the function `createTheme()`)
import { Theme } from '@mui/material/styles';
declare module '@mui/styles' {
interface DefaultTheme extends Theme {}
}
Nested imports of more than one level are private. For example, you can no longer import red from @mui/material/colors/red.
-import red from '@mui/material/colors/red';
+import { red } from '@mui/material/colors';
fade() was renamed to alpha() to better describe its functionality.
The previous name caused confusion when the input color already had an alpha value. The helper overrides the alpha value of the color.
-import { fade } from '@mui/material/styles';
+import { alpha } from '@mui/material/styles';
const classes = makeStyles(theme => ({
- backgroundColor: fade(theme.palette.primary.main, theme.palette.action.selectedOpacity),
+ backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
}));
The createStyles function from @mui/material/styles was moved to the one exported from @mui/styles. It is necessary for removing the dependency on @mui/styles in the Material UI npm package.
-import { createStyles } from '@mui/material/styles';
+import { createStyles } from '@mui/styles';
The createGenerateClassName function is no longer exported from @mui/material/styles.
You can import it from the deprecated @mui/styles package if you need to continue using it.
-import { createGenerateClassName } from '@mui/material/styles';
+import { createGenerateClassName } from '@mui/styles';
To generate custom class names without using @mui/styles, check out ClassName Generator for more details.
The function createMuiTheme was renamed to createTheme() to make it more intuitive to use with ThemeProvider.
-import { createMuiTheme } from '@mui/material/styles';
+import { createTheme } from '@mui/material/styles';
-const theme = createMuiTheme({
+const theme = createTheme({
The MuiThemeProvider component is no longer exported from @mui/material/styles. Use ThemeProvider instead.
-import { MuiThemeProvider } from '@mui/material/styles';
+import { ThemeProvider } from '@mui/material/styles';
The jssPreset object is no longer exported from @mui/material/styles.
You can import it from the deprecated @mui/styles package if you need to continue using it.
-import { jssPreset } from '@mui/material/styles';
+import { jssPreset } from '@mui/styles';
makeStyles importSince Material UI v5 doesn't use JSS, the JSS-based makeStyles utility is no longer exported by @mui/material/styles.
While migrating your app away from JSS, you can temporarily import this deprecated utility from @mui/styles/makeStyles before refactoring your components further.
Make sure to add a ThemeProvider at the root of your application, as the defaultTheme is no longer available.
If you are using this utility together with @mui/material, it's recommended that you use the ThemeProvider component from @mui/material/styles instead.
-import { makeStyles } from '@mui/material/styles';
+import { makeStyles } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const theme = createTheme();
const useStyles = makeStyles((theme) => ({
background: theme.palette.primary.main,
}));
function Component() {
const classes = useStyles();
return <div className={classes.root} />
}
// In the root of your app
function App(props) {
- return <Component />;
+ return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>;
}
The ServerStyleSheets component is no longer exported from @mui/material/styles.
You can import it from the deprecated @mui/styles package if you need to continue using it.
-import { ServerStyleSheets } from '@mui/material/styles';
+import { ServerStyleSheets } from '@mui/styles';
Since Material UI v5 doesn't use JSS, the JSS-based styled utility exported by @mui/material/styles has been replaced with an equivalent Emotion-based utility that's not backwards compatible.
While migrating your app away from JSS, you can temporarily import the JSS-based utility from the deprecated @mui/styles package before refactoring your components further.
Make sure to add a ThemeProvider at the root of your application, as the defaultTheme is no longer available.
If you are using this utility together with @mui/material, it's recommended you use the ThemeProvider component from @mui/material/styles instead.
-import { styled } from '@mui/material/styles';
+import { styled } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const theme = createTheme();
const MyComponent = styled('div')(({ theme }) => ({ background: theme.palette.primary.main }));
function App(props) {
- return <MyComponent />;
+ return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>;
}
The StylesProvider component is no longer exported from @mui/material/styles.
You can import it from the deprecated @mui/styles package if you need to continue using it.
-import { StylesProvider } from '@mui/material/styles';
+import { StylesProvider } from '@mui/styles';
The useThemeVariants hook is no longer exported from @mui/material/styles.
You can import it from the deprecated @mui/styles package if you need to continue using it.
-import { useThemeVariants } from '@mui/material/styles';
+import { useThemeVariants } from '@mui/styles';
Since Material UI v5 doesn't use JSS, the JSS-based withStyles utility is no longer exported by @mui/material/styles.
While migrating your app away from JSS, you can temporarily import this deprecated utility from @mui/styles/withStyles before refactoring your components further.
Make sure to add a ThemeProvider at the root of your application, as the defaultTheme is no longer available.
If you are using this utility together with @mui/material, you should use the ThemeProvider component from @mui/material/styles instead.
-import { withStyles } from '@mui/material/styles';
+import { withStyles } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const defaultTheme = createTheme();
const MyComponent = withStyles((props) => {
const { classes, className, ...other } = props;
return <div className={clsx(className, classes.root)} {...other} />
})(({ theme }) => ({ root: { background: theme.palette.primary.main }}));
function App() {
- return <MyComponent />;
+ return <ThemeProvider theme={defaultTheme}><MyComponent /></ThemeProvider>;
}
Replace the innerRef prop with the ref prop. Refs are now automatically forwarded to the inner component.
import * as React from 'react';
import { withStyles } from '@mui/styles';
const MyComponent = withStyles({
root: {
backgroundColor: 'red',
},
})(({ classes }) => <div className={classes.root} />);
function MyOtherComponent(props) {
const ref = React.useRef();
- return <MyComponent innerRef={ref} />;
+ return <MyComponent ref={ref} />;
}
The withTheme HOC utility has been removed from the @mui/material/styles package. You can use @mui/styles/withTheme instead.
Make sure to add a ThemeProvider at the root of your application, as the defaultTheme is no longer available.
If you are using this utility together with @mui/material, it's recommended you use the ThemeProvider component from @mui/material/styles instead.
-import { withTheme } from '@mui/material/styles';
+import { withTheme } from '@mui/styles';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
+const theme = createTheme();
const MyComponent = withTheme(({ theme }) => <div>{theme.direction}</div>);
function App(props) {
- return <MyComponent />;
+ return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>;
}
This HOC was removed. If you need this feature, you can try the alternative that uses the useMediaQuery hook.
The GitHub icon was reduced in size from 24px to 22px wide to match the size of the other icons.
We have a dedicated page for migrating @material-ui/pickers to v5.
The following system functions and properties were renamed because they are considered deprecated CSS:
gridGap becomes gapgridRowGap becomes rowGapgridColumnGap becomes columnGapUse a spacing unit in gap, rowGap, and columnGap. If you were using a number previously, you need to mention the px to bypass the new transformation with theme.spacing.
<Box
- gap={2}
+ gap="2px"
>
Replace css prop with sx to avoid collision with styled-components and Emotion's css prop.
-<Box css={{ color: 'primary.main' }} />
+<Box sx={{ color: 'primary.main' }} />
:::warning The system grid function was not documented in v4. :::