CSS 主题变量 - 配置
Material UI 中配置 CSS 主题变量的指南。
定制变量前缀
要更改默认变量前缀 (--mui
),请将字符串提供给 cssVarPrefix
属性,如下所示
createTheme({ cssVariables: { cssVarPrefix: 'any' } });
// generated stylesheet:
// --any-palette-primary-main: ...;
要删除前缀,请使用空字符串作为值
createTheme({ cssVariables: { cssVarPrefix: '' } });
// generated stylesheet:
// --palette-primary-main: ...;
手动切换暗黑模式
要手动在模式之间切换,请使用以下选择器之一设置 colorSchemeSelector
createTheme({
colorSchemes: { light: true, dark: true },
cssVariables: {
colorSchemeSelector: 'class'
}
});
// CSS Result
.light { ... }
.dark { ... }
然后,使用 useColorScheme
Hook 在模式之间切换
import { useColorScheme } from '@mui/material/styles';
function ModeSwitcher() {
const { mode, setMode } = useColorScheme();
if (!mode) {
return null;
}
return (
<select
value={mode}
onChange={(event) => {
setMode(event.target.value);
// For TypeScript, cast `event.target.value as 'light' | 'dark' | 'system'`:
}}
>
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
);
}
确定系统模式
要确定系统模式是 light
还是 dark
,请使用 systemMode
属性
const { mode, systemMode } = useColorScheme();
console.log(mode); // 'system'
console.log(systemMode); // 'light' | 'dark'
但是,如果模式 **不是** system
,则 systemMode
将为 undefined
。
const { mode, systemMode } = useColorScheme();
console.log(mode); // 'light' | 'dark'
console.log(systemMode); // undefined
防止 SSR 闪烁
对于 SSR(服务器端渲染)应用程序,Material UI 无法在服务器上检测到用户选择的模式,从而导致屏幕在客户端 hydration 阶段从亮到暗闪烁。
要防止此问题,您需要确保代码库中没有使用 theme.palette.mode === 'dark'
。
如果您有这样的条件,请将其替换为 theme.applyStyles()
函数
import Card from '@mui/material/Card';
function App() {
return (
<Card
- sx={(theme) => ({
- backgroundColor: theme.palette.mode === 'dark' ? '#000' : '#fff',
- '&:hover': {
- backgroundColor: theme.palette.mode === 'dark' ? '#333' : '#f5f5f5',
- },
- })}
+ sx={[
+ {
+ backgroundColor: '#fff',
+ '&:hover': {
+ backgroundColor: '#f5f5f5',
+ },
+ },
+ (theme) =>
+ theme.applyStyles('dark', {
+ backgroundColor: '#000',
+ '&:hover': {
+ backgroundColor: '#333',
+ },
+ }),
+ ]}
/>
);
}
接下来,如果您有 **不是** media
的自定义选择器,请根据您使用的框架添加 InitColorSchemeScript
组件
Next.js App Router
将以下代码添加到 根布局 文件
import InitColorSchemeScript from '@mui/material/InitColorSchemeScript';
export default function RootLayout(props) {
return (
<html lang="en" suppressHydrationWarning>
<body>
{/* must come before the <main> element */}
<InitColorSchemeScript attribute="class" />
<main>{children}</main>
</body>
</html>
);
}
Next.js Pages Router
将以下代码添加到自定义 pages/_document.js
文件
import Document, { Html, Head, Main, NextScript } from 'next/document';
import InitColorSchemeScript from '@mui/material/InitColorSchemeScript';
export default class MyDocument extends Document {
render() {
return (
<Html>
<Head>...</Head>
<body>
{/* must come before the <Main> element */}
<InitColorSchemeScript attribute="class" />
<Main />
<NextScript />
</body>
</Html>
);
}
}
Gatsby
将脚本放置在您的 gatsby-ssr.js
文件中
import * as React from 'react';
import InitColorSchemeScript from '@mui/material/InitColorSchemeScript';
export function onRenderBody({ setPreBodyComponents }) {
setPreBodyComponents([<InitColorSchemeScript attribute="class" />]);
}
强制特定颜色方案
要为应用程序的某些部分强制特定颜色方案,请将选择器直接设置为组件或 HTML 元素。
在以下示例中,div
内的所有组件将始终为暗黑模式
// if the selector is '.mode-%s'
<div className=".mode-dark">
<Paper sx={{ p: 2 }}>
<TextField label="Email" type="email" margin="normal" />
<TextField label="Password" type="password" margin="normal" />
<Button>Sign in</Button>
</Paper>
{/* other components */}
</div>
禁用 CSS 颜色方案
默认情况下,createTheme()
基于调色板模式附加 CSS color-scheme
属性。您可以通过将 disableCssColorScheme
设置为 true
来禁用此功能
createTheme({
cssVariables: { disableCssColorScheme: true },
});
生成的 CSS 将不包含 color-scheme
属性
@media (prefers-color-scheme: dark) {
:root {
- color-scheme: dark;
--mui-palette-primary-main: #90caf9;
...
}
}
颜色方案之间的即时过渡
要在模式之间切换时禁用 CSS 过渡效果,请应用 disableTransitionOnChange
属性
<ThemeProvider disableTransitionOnChange />
强制在模式之间重新计算主题
默认情况下,当主题中设置了 cssVariables: true
时,在浅色和深色模式之间切换时,ThemeProvider
不会重新渲染。
如果您想选择退出此行为,请在 ThemeProvider 中使用 forceThemeRerender
属性
<ThemeProvider forceThemeRerender />