CSS 主题变量
采用 Material UI 或 Joy UI 中的 CSS 主题变量概述。
CSS 变量 是一种现代的跨浏览器功能,允许您在 CSS 中声明变量并在其他属性中重复使用它们。
简介
CSS 主题变量支持是 MUI System 在 v5.0.5
中新增的一项实验性导出功能。它指示底层的 Material UI、Joy UI 甚至自定义 UI 库组件使用生成的 CSS 主题变量而不是原始值。这显著改善了与主题化和自定义相关的开发者体验。借助这些变量,您可以在构建时将主题注入到应用程序的样式表中,以便在渲染整个应用程序之前应用用户选择的设置。了解更多关于使用 CSS 主题变量的优势和权衡。
优势
- 它使您能够防止 暗黑模式 SSR 闪烁。
- 您可以创建超出
light
和dark
的无限色彩方案。 - 它为开发者以及团队中的设计师提供了更好的调试体验。
- 您网站的色彩方案在浏览器标签页之间自动同步。
- 它简化了与第三方工具的集成,因为 CSS 主题变量是全局可用的。
- 当您想将暗色样式应用于应用程序的特定部分时,它可以减少对嵌套主题的需求。
权衡
对于服务端应用程序,有一些权衡需要考虑
与默认方法比较 | 原因 | |
---|---|---|
HTML 大小 | 更大 | CSS 变量在构建时为浅色和深色模式生成。 |
首次内容绘制 (FCP) | 更长 | 由于 HTML 大小更大,因此在显示内容之前下载 HTML 的时间会稍长。 |
可交互时间 (TTI) | 更短(对于暗黑模式) | 样式表不会在浅色和深色模式之间重新生成,运行 JavaScript 代码花费的时间大大减少。 |
用法
CSS 变量 API 用法作为一个高阶函数 unstable_createCssVarsProvider
公开,可以调用它来创建主题提供器和其他实用程序,以便在您的应用程序中共享主题配置。这是一个非常底层的函数,有很多组成部分。如果您正在使用 Material UI 或 Joy UI,它们会公开自己的 CssVarsProvider
组件,您可以直接使用它,而无需配置您的主题。
我们将首先为浅色和深色模式定义一个最小主题调色板。
// extendTheme.js
import {
unstable_createGetCssVar as systemCreateGetCssVar,
unstable_prepareCssVars as prepareCssVars,
} from '@mui/system';
const lightColorScheme = {
palette: {
mode: 'light',
primary: {
default: '#3990FF',
dark: '#02367D',
},
text: {
default: '#111111',
},
// ... other colors
},
};
const darkColorScheme = {
palette: {
mode: 'dark',
primary: {
default: '#265D97',
dark: '#132F4C',
main: '#5090D3',
},
text: {
default: '#ffffff',
},
// ... other colors
},
};
const createGetCssVar = (cssVarPrefix = 'my-app') =>
systemCreateGetCssVar(cssVarPrefix);
function extendTheme({ cssVarPrefix = 'my-app' } = {}) {
const getCssVar = createGetCssVar(cssVarPrefix);
const theme = {
colorSchemes: {
light: lightColorScheme,
dark: darkColorScheme,
},
// ... any other objects independent of color-scheme,
// like fontSizes, spacing tokens, etc
};
const { vars: themeVars, generateCssVars } = prepareCssVars(
{ colorSchemes: theme.colorSchemes },
{
prefix: cssVarPrefix,
},
);
theme.vars = themeVars;
theme.generateCssVars = generateCssVars;
theme.palette = {
...theme.colorSchemes.light.palette,
colorScheme: 'light',
};
return theme;
}
const myCustomDefaultTheme = extendTheme();
export default myCustomDefaultTheme;
在这里,返回的 theme
对象需要遵循一定的结构,才能被最终的 CssVarsProvider
正确使用。它应该有一个 colorSchemes
键,其中包含浅色和深色(以及任何其他)调色板。从 @mui/system
导入的 prepareCssVars
用于创建 CSS 变量名,然后可以使用返回的 vars
轻松访问这些变量名。这也添加到 theme
对象中。最后,创建了 myCustomDefaultTheme
主题对象,现在可以将其传递给 createCssVarsProvider
以获取 CssVarsProvider
。
// CssVarsProvider.js
import { unstable_createCssVarsProvider as createCssVarsProvider } from '@mui/system';
const { CssVarsProvider, useColorScheme } = createCssVarsProvider({
defaultColorScheme: {
light: 'light',
dark: 'dark',
},
theme: myCustomDefaultTheme,
});
export { CssVarsProvider, useColorScheme };
现在用这个 CssVarsProvider
组件包裹您的顶层应用程序组件,然后您可以访问传递给在提供器内部渲染的任何组件的主题值。
使用 CSS 变量的组件示例 -
// Button.js
import { styled } from '@mui/system';
const Button = styled('button')(({ theme }) => ({
backgroundColor: theme.vars.palette.primary.default,
border: `1px solid ${theme.vars.palette.primary.dark}`,
color: theme.vars.palette.text.default,
}));
export default Button;
Hook useColorScheme
可用于获取当前的 mode
(浅色或深色),也可以像这样更新模式
// App.js
function App() {
const { setMode, mode } = useColorScheme();
const toggleMode = () => {
setMode(mode === 'dark' ? 'light' : 'dark');
};
return (
<div>
<h1>Current Mode: {mode}</h1>
<Button onClick={toggleMode}>Toggle Mode</Button>
</div>
);
}
// main.js
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import App from './App';
import { CssVarsProvider } from './CssVarsProvider';
ReactDOM.createRoot(document.getElementById('root')).render(
<CssVarsProvider>
<App />
</CssVarsProvider>,
);
现在,Button 的 backgroundColor
、borderColor
和文本 color
值将正确地使用基于所选 mode
的颜色。
演示
有关框架或语言特定的设置说明,请参阅CSS 主题变量—用法—服务端渲染。 有关框架或语言特定的设置,请参阅此处
请参阅 Material UI 和 Joy UI 中 createCssVarsProvider
的完整用法。
API
createCssVarsProvider
选项
modeStorageKey?
: localStorage 键,用于存储应用程序mode
(默认为mode
)colorSchemeStorageKey?
: localStorage 键,用于存储colorScheme
defaultColorScheme
: 设计系统默认色彩方案(字符串或对象,取决于设计系统是否有一个或多个主题,可以是light
或dark
)defaultMode?
: 设计系统默认模式(默认为light
)disableTransitionOnChange?
: 禁用在模式或色彩方案之间切换时的 CSS 过渡效果(默认为false
)themeId?
: 设计系统的唯一 ID,用于在有多个设计系统时获取对应的主题。theme
: 设计系统默认主题。除了createCssVarsProvider
的最低要求外,其结构由设计系统实现决定。resolveTheme(theme: Theme) => Theme
: 在 CSS 变量附加后调用的函数。此函数的返回值将是传递给ThemeProvider
的最终主题。
createCssVarsProvider
返回 3 项。
<CssVarsProvider>
属性
defaultMode?: 'light' | 'dark' | 'system'
- 应用程序的默认模式(默认为light
)disableTransitionOnChange : boolean
- 禁用在模式之间切换时的 CSS 过渡效果theme: ThemeInput
- 提供给 React 上下文的主题。它应具有以下字段colorSchemes: { [key: string]: ColorScheme }
- 应用程序的色彩方案colorSchemeSelector: 'media' | 'class' | 'data' | string
: - 应用 CSS 主题变量和组件样式的方法generateStyleSheets: () => Record<string, string>
- 生成 CSS 变量的函数generateThemeVars: () => Record<string, any>
- 生成theme.vars
的 CSS 变量引用的函数
modeStorageKey?: string
- localStorage 键,用于存储应用程序mode
useColorScheme: () => ColorSchemeContextValue
mode: string
- 用户选择的模式setMode: mode => {…}
- 用于设置mode
的函数。mode
将保存到内部状态和本地存储;如果mode
为 null,则将重置为默认模式
getInitColorSchemeScript: (options) => React.ReactElement
选项
defaultMode?: 'light' | 'dark' | 'system'
: - React 渲染树之前应用程序的默认模式(默认为light
)modeStorageKey?: string
: - localStorage 键,用于存储应用程序mode
attribute?: string
- 用于应用色彩方案的 DOM 属性