跳到主要內容
+

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?:用於儲存應用程式 mode 的 localStorage 鍵 (預設為 mode)
  • colorSchemeStorageKey?:用於儲存 colorScheme 的 localStorage 鍵
  • defaultColorScheme:設計系統預設色彩配置(字串或物件,取決於設計系統是否具有 1 個或多個主題,可以是 lightdark
  • defaultMode?:設計系統預設模式 (預設為 light)
  • disableTransitionOnChange?:在模式或色彩配置之間切換時停用 CSS 轉換 (預設為 false)
  • themeId?:設計系統的唯一 ID,用於在有多個設計系統時取得對應的主題。
  • theme:設計系統預設主題。除了 createCssVarsProvider 的最低要求外,其結構由設計系統實作決定。
  • resolveTheme(theme: Theme) => Theme:在附加 CSS 變數後要呼叫的函式。此函式的結果將是傳遞給 ThemeProvider 的最終主題。

createCssVarsProvider 傳回 3 個項目。

<CssVarsProvider> props

  • defaultMode?: 'light' | 'dark' | 'system' - 應用程式的預設模式 (預設為 light)
  • disableTransitionOnChange : boolean - 在模式之間切換時停用 CSS 轉換
  • theme: ThemeInput - 提供給 React context 的主題。它應該具有以下欄位
    • colorSchemes: { [key: string]: ColorScheme } - 應用程式的色彩配置
    • colorSchemeSelector: 'media' | 'class' | 'data' | string: - 套用 CSS 主題變數和組件樣式的方法
    • generateStyleSheets: () => Record<string, string> - 用於產生 CSS 變數的函式
    • generateThemeVars: () => Record<string, any> - 用於為 theme.vars 產生 CSS 變數參考的函式
  • modeStorageKey?: string - 用於儲存應用程式 mode 的 localStorage 鍵

useColorScheme: () => ColorSchemeContextValue

  • mode: string - 使用者選取的模式
  • setMode: mode => {…} - 用於設定 mode 的函式。mode 會儲存到內部狀態和本機儲存空間;如果 mode 為 null,則會重設為預設模式

getInitColorSchemeScript: (options) => React.ReactElement

選項

  • defaultMode?: 'light' | 'dark' | 'system': - React 呈現樹狀結構之前的應用程式預設模式 (預設為 light)
  • modeStorageKey?: string: - 用於儲存應用程式 mode 的 localStorage 鍵
  • attribute?: string - 用於套用色彩配置的 DOM 屬性