Theming And Variables
如果你發現自己在多個 components 裡一直重複寫顏色分支,問題多半是 design tokens,並不是少了什麼 runtime logic。
在 config 中定義 variables
ts
import { defineEngineConfig } from '@pikacss/core'
export default defineEngineConfig({
variables: {
variables: {
// 簡單變數(預設會輸出在 :root 之下)
'--color-bg': '#ffffff',
'--color-text': '#1a1a1a',
// 值為 null 的變數(只提供 autocomplete,不會真的輸出 CSS)
'--external-var': null,
// 掛在 selector 範圍下的 variables
'[data-theme="dark"]': {
'--color-bg': '#1a1a1a',
'--color-text': '#ffffff',
},
// 帶有進階設定的 variable
'--spacing-unit': {
value: '4px',
autocomplete: {
asValueOf: ['margin', 'padding', 'gap'],
asProperty: true,
},
pruneUnused: false, // 永遠包含在輸出中
},
},
// 是否要從最終 CSS 移除未使用的 variables
pruneUnused: true,
// 不管有沒有被使用,都會一律保留的 variables
safeList: ['--color-bg', '--color-text'],
},
})你也可以把 variable definitions 放在 selectors 之下,替不同主題建立各自的值。
ts
import { defineEngineConfig } from '@pikacss/core'
export default defineEngineConfig({
variables: {
variables: {
// 基礎 token,不會直接在任何 atomic style 中被引用
'--spacing-base': '4px',
// 衍生 token,會在值中引用 --spacing-base
'--spacing-lg': 'calc(var(--spacing-base) * 4)',
},
pruneUnused: true,
// --spacing-base is not in safeList and is never used in pika() calls directly.
// 但因為 --spacing-lg(它本身有被使用)會透過 var() 引用它,
// BFS 展開會確保 --spacing-base 也會被保留在 CSS 輸出中。
},
})在 components 中使用 variables
ts
const className = pika({
color: 'var(--color-text)',
backgroundColor: 'var(--color-bg)',
})css
/* Preflight:變數宣告 */
:root {
--color-primary: #0ea5e9;
--color-bg: #ffffff;
--color-text: #1e293b;
}
[data-theme="dark"] {
--color-bg: #0f172a;
--color-text: #e2e8f0;
}
/* 由 pika() 產生的 atomic styles */
.pk-a { color: var(--color-text); }
.pk-b { background-color: var(--color-bg); }如果 variable 的值需要在 runtime 依每個實例變動,請看 Dynamic Values 與 CSS Variables。
一個實用的主題化策略
- 用 selectors 描述 light 或 dark 這類主題情境。
- 用 variables 承載實際的 token values。
- 讓 component style definitions 專注在語意化 token 的使用。
比起直接複製一整份深色和淺色的 component objects,這種拆法通常更容易維護。
該做與不該做
| 該做 | 不該做 |
|---|---|
| 把主題值放進 CSS variables。 | 沒有必要地為每個主題複製整個 component。 |
| 用 selectors 來界定 variable definitions 的範圍。 | 把主題邏輯塞進 runtime object construction。 |
| 讓 component objects 保持語意化。 | 在每個 component 裡把所有 token 都直接寫死。 |