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?
:用於儲存應用程式mode
的 localStorage 鍵 (預設為mode
)colorSchemeStorageKey?
:用於儲存colorScheme
的 localStorage 鍵defaultColorScheme
:設計系統預設色彩配置(字串或物件,取決於設計系統是否具有 1 個或多個主題,可以是light
或dark
)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 屬性