OKLCH 色調色板公式
一個產品的中性色調(頁面底色、卡片表面、凹槽、細線、四級文字)通常每個主題需要 15 到 30 個由肉眼挑選的十六進位色碼。這些色碼會逐漸偏移,深色模式需要另一套手選集合,而且沒有人知道哪些配對仍然符合對比度標準。用公式取代它們:
表面層級記號: L = 紙白 + 深度 × n(記號) 彩度 = 著色 色相 = 色相
文字記號: L = 墨水 + 階梯 × n(記號) 彩度 = 墨水-著色 色相 = 色相
n(記號) 是記號在梯級上的位置,每個主題有一個梯級。移動一個輸入值,整個色階就會一起移動,因此階梯之間的間距(也就是對比度所在之處)能在重新配色時保持不變。重新為一個產品配色只需一行程式碼(--hue)。
三個旋鈕(--hue、--lightness、--chroma 或 --contrast)驅動所有顏色。
檔案
references/palette.css:附有起始輸入值和梯級的現成規則。scripts/fit_palette.py:將輸入值擬合到現有的十六進位色調色板,並印出每個記號的 ΔE。scripts/ladders.json:預設梯級(淺色、深色)。scripts/palette-audit.mjs:在真實瀏覽器中解析兩個主題的每個記號,並在對比度失敗時報錯。scripts/oklch.py:轉換函式以及 ΔE / WCAG 輔助工具。
操作步驟
-
根據角色而非數值來命名記號。 預設值:
- 底色:
ground(頁面)、panel(導覽列、工具列)、surface(卡片、選單)、surface-2(凹槽)、surface-3(晶片、懸停列)、field。 - 線條:
line、line-2、line-3(細線,從最淺到最深),加上field-line(控制元件的邊緣,必須達到 3:1)。 - 文字:
ink、ink-2、ink-3、ink-4(文字,從最深到最淡)。每個文字階梯都是文字,因此每個都必須達到 4.5:1。
- 底色:
-
擬合,而不是重新挑選。 對於現有產品,執行
python3 scripts/fit_palette.py theme.css。它會讀取--color-*的十六進位宣告(淺色,然後是[data-theme="dark"]規則),將輸入值擬合到預設梯級,並印出每個記號的 ΔE。低於 2 視覺上無法分辨。 -
在設計需要不同空間分配時覆寫梯級步驟,而不是修改顏色。使用
fit_palette.py theme.css light '<inputs>' '<overrides>'評估候選方案,直到最差的 ΔE 低於 ~2。 常見覆寫:field: 0(欄位是卡片表面)、更寬的line-3、ink和ink-2之間更大的間距。 -
撰寫規則(請參閱
references/palette.css):- 將輸入值和
--color-*公式放在承載主題屬性的元素上。 - 在深色規則中重新宣告你變更的每個輸入值。否則,為套件預設值編寫的深色規則會以它的值勝出。
- 在 Tailwind v4 中,將記號名稱保留在
@theme中,以便工具類別存在;執行階段的宣告會覆寫它們。
- 將輸入值和
-
在真實瀏覽器中稽核:
node scripts/palette-audit.mjs <url>。它會繪製每個記號、讀回 sRGB,並檢查:- 每個文字階梯與每個底色之間的 4.5:1 對比度;
field-line和ring的 3:1 對比度。
修正 FAIL 的方法是移動該記號的梯級步驟,而不是為顏色特設例外。預期現有色調色板會出現 FAIL:在一次 17 個應用的遷移中,稽核發現超過一半的應用有
ink-4或field-line值失敗,而這些值之前都已出貨。
陷阱
var()在自訂屬性內部的解析位置是它被宣告的地方。- 在
:root上宣告公式並在子元素上設定輸入值:子元素永遠不會重新上色。 - 別名記號(
--color-heading: var(--color-ink))必須也在同一個主題元素上宣告。
- 在
- Tailwind v4 的
@theme數值存在於:root上。 作用域在某個應用根元素([data-app])的主題必須在該處宣告公式,而不是在@theme中。 - 任何將顏色交給 Canvas 或地圖函式庫的場景(
getComputedStyle(...).getPropertyValue('--color-x'))現在會收到一個未解析的oklch(calc(...))字串。請先解析它:繪製一個探針元素並讀取 1px 的 Canvas,方式與稽核相同。 - 底色和文字使用同一色相。 如果設計的文字色相與底色不同,請保持
--ink-tint較低;在 L 0.98 時,任何彩度都會被視為色偏。 - 品牌色、狀態色和圖表色應保持在公式之外。 從相同色相、固定明度推導出文字在著色背景上的變體(例如
brand-text),而不是單獨挑選。 - 從合成圖取樣的混合色相、僅淺色主題的色調色板,可能無法在 ~2 ΔE 內擬合。 與其扭曲設計,不如跳過它們。稽核仍然適用。