在 MUI 5 中讓自定義的 CSS 樣式擁有較高的權重
總結
簡單來說就是透過元件 StyledEngineProvider
搭配 injectFirst
來讓 MUI 的樣式先被注入,接著才是引入使用者自定義的 CSS 內容。如此一來可以不用把所有需要追加到 MUI 元件的樣式都放到 styleOverrides
中來處理、也可避免在自訂樣式中透過 !important
來覆蓋掉 MUI 的設定。
版本與環境
@mui/material: ^5.0.0
筆記
使用實例
使用方式如下:
打開 DevTool 可看到 MUI 的樣式被提前到 head 第一順位,下方才接著是使用者自訂的 CSS 內容:
而以下是沒有使用 injectFirst
的情況,可以看到使用者自定義的 h1 樣式被 MUI 的設定覆蓋掉:
沒有搭配 injectFirst
時會讓 MUI 的設定壓軸引入,樣式權重會比使用者定義的 CSS 來得高:
原始碼部分
追蹤 import { StyledEngineProvider } from "@mui/material/styles";
會發現 StyledEngineProvider
的本體位在 material-ui/packages/mui-styled-engine/src/StyledEngineProvider/StyledEngineProvider.js
中(repo 連結在此),而檔案中的註解也有說明:當使用者傳入 props.injectFirst = true
時,會讓樣式被移動到 <head>
的最上方。
import * as React from 'react';
import PropTypes from 'prop-types';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
// prepend: true moves MUI styles to the top of the <head> so they're loaded first.
// It allows developers to easily override MUI styles with other styling solutions, like CSS modules.
const cache = createCache({ key: 'css', prepend: true });
export default function StyledEngineProvider(props) {
const { injectFirst, children } = props;
return injectFirst ? (
<CacheProvider value={cache}>{children}</CacheProvider>
) : (
children
);
}
StyledEngineProvider.propTypes = {
/**
* Your component tree.
*/
children: PropTypes.node,
/**
* By default, the styles are injected last in the <head> element of the page.
* As a result, they gain more specificity than any other style sheet.
* If you want to override MUI's styles, set this prop.
*/
injectFirst: PropTypes.bool,
};
查詢 @emotion/cache
createCache
的官方文件也可看到 prepend
的功能:
prepend: A
boolean
representing whether to prepend rather than append style tags into the specified container DOM node.
結論:使用 StyledEngineProvider
搭配 injectFirst
可確保使用者自訂的樣式獲得較高的權重。