跳到内容
+

CSS 主题变量

采用 Material UI 或 Joy UI 中的 CSS 主题变量概述。

CSS 变量 是一种现代的跨浏览器功能,允许您在 CSS 中声明变量并在其他属性中重复使用它们。

简介

CSS 主题变量支持是 MUI System 在 v5.0.5 中新增的一项实验性导出功能。它指示底层的 Material UI、Joy UI 甚至自定义 UI 库组件使用生成的 CSS 主题变量而不是原始值。这显著改善了与主题化和自定义相关的开发者体验。借助这些变量,您可以在构建时将主题注入到应用程序的样式表中,以便在渲染整个应用程序之前应用用户选择的设置。了解更多关于使用 CSS 主题变量的优势权衡

优势

  • 它使您能够防止 暗黑模式 SSR 闪烁
  • 您可以创建超出 lightdark 的无限色彩方案。
  • 它为开发者以及团队中的设计师提供了更好的调试体验。
  • 您网站的色彩方案在浏览器标签页之间自动同步。
  • 它简化了与第三方工具的集成,因为 CSS 主题变量是全局可用的。
  • 当您想将暗色样式应用于应用程序的特定部分时,它可以减少对嵌套主题的需求。

权衡

对于服务端应用程序,有一些权衡需要考虑

与默认方法比较 原因
HTML 大小 更大 CSS 变量在构建时为浅色和深色模式生成。
首次内容绘制 (FCP) 更长 由于 HTML 大小更大,因此在显示内容之前下载 HTML 的时间会稍长。
可交互时间 (TTI) 更短(对于暗黑模式) 样式表不会在浅色和深色模式之间重新生成,运行 JavaScript 代码花费的时间大大减少。

用法

CSS 变量 API 用法作为一个高阶函数 unstable_createCssVarsProvider 公开,可以调用它来创建主题提供器和其他实用程序,以便在您的应用程序中共享主题配置。这是一个非常底层的函数,有很多组成部分。如果您正在使用 Material UIJoy 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 的 backgroundColorborderColor 和文本 color 值将正确地使用基于所选 mode 的颜色。

演示

Enter 键开始编辑

有关框架或语言特定的设置说明,请参阅CSS 主题变量—用法—服务端渲染。 有关框架或语言特定的设置,请参阅

请参阅 Material UIJoy UIcreateCssVarsProvider 的完整用法。

API

createCssVarsProvider 选项

  • modeStorageKey?: localStorage 键,用于存储应用程序 mode(默认为 mode
  • colorSchemeStorageKey?: localStorage 键,用于存储 colorScheme
  • defaultColorScheme: 设计系统默认色彩方案(字符串或对象,取决于设计系统是否有一个或多个主题,可以是 lightdark
  • 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 属性