CSS color-mix() 與 OKLCH:從品牌色產生互動配色與備援值
GDESIGN
設計發布: 7 分鐘閱讀

CSS color-mix() 與 OKLCH:從品牌色產生互動配色與備援值

品牌色只是介面配色的起點。滑鼠懸停、按下、停用、背景與框線,都需要彼此相關的顏色。CSS 的 color-mix() 與 OKLCH 可以把這些關係寫成共用公式。

但「能算出顏色」與「文字可讀、狀態清楚」是兩件事。本文以兩色混合和 CSS 自訂屬性為範圍,搭配淺色、深色主題及備援值的驗證方式。

日文原文發布: 2026-04-23

sRGB、HSL 與 OKLCH 描述的事情不同

sRGB 是網頁常用的 RGB 色彩空間;HSL 以色相、飽和度和明度描述 RGB 顏色,但相同 HSL 明度不代表看起來一樣亮。

例如 hsl(60 100% 50%)hsl(240 100% 50%) 的 HSL 明度相同,相對亮度卻差很多。HSL 明度由 RGB 最大與最小分量計算,並不是知覺均勻的尺度。

CIELAB 與 Oklab 試圖讓色彩差異更貼近人類知覺。Björn Ottosson 在 2020 年發表 Oklab,OKLCH 是它的極座標表示法。知覺均勻性仍是近似,不能保證所有顏色與觀看條件都完全一致。

讀懂 OKLCH 的 L、C、H

  • L(明度):常以 0 到 1,或百分比表示。
  • C(彩度):0 表示無彩色。常見的 0.4 並不是規格上限;可顯示範圍取決於明度、色相及目標色域。
  • H(色相):色相圓上的角度,通常以度數表示。
oklch(62.3% 0.214 259.815)
oklch(0.623 0.214 259.815)

這兩種寫法表示同一個顏色,也是 Tailwind CSS v4 的 blue-500 定義。Oklab 的設計目標包含改善藍色區域的知覺表現,也能描述超出 sRGB 的顏色,但不代表每台螢幕都能完整顯示任意 OKLCH 值。

保持 L 一致,有助於協調不同色相的明度;不過,OKLCH 的 L 不是 WCAG 相對亮度。與實際背景的對比值仍要另外計算。

混色空間、比例與色相路徑

以下範例指定色彩空間與兩個顏色。省略百分比、比例正規化及 alpha 都會影響結果:

color-mix(in srgb, red 50%, blue)
color-mix(in oklch, #2563eb 80%, white)
color-mix(in oklch, #2563eb, black 30%)
color-mix(in oklch longer hue, red, blue)

前三個範例分別是 50:50、80:20、70:30。在極座標色彩空間中,shorter huelonger hue 等選項會改變色相的插值路徑。使用 OKLCH 並不保證每次混色都符合設計意圖,也不保證中間色一定鮮豔。

混入透明色會改變 alpha,實際看到的顏色還取決於背景合成。超出顯示色域的值也可能經過色域對應,因此應查看最終呈現結果,而不是只憑語法判斷。

從一個品牌色產生多種狀態

先定義品牌色,再讓各種狀態引用同一個輸入:

:root {
  --brand: #2563eb;
  --brand-hover: color-mix(in oklch, var(--brand), white 15%);
  --brand-active: color-mix(in oklch, var(--brand), black 15%);
  --brand-disabled: color-mix(in oklch, var(--brand), transparent 60%);
  --brand-border: color-mix(in oklch, var(--brand), white 70%);
  --brand-bg: color-mix(in oklch, var(--brand), white 92%);
  --brand-focus: color-mix(in oklch, var(--brand), transparent 70%);
}
.button {
  background: var(--brand);
  border: 1px solid var(--brand-border);
}
.button:hover { background: var(--brand-hover); }
.button:active { background: var(--brand-active); }
.button:disabled { background: var(--brand-disabled); }

改變 --brand,其他顏色就會依同一套關係更新。這是產生配色的範例,不是已通過無障礙檢查的完整色票。若按鈕使用白字,讓懸停背景變亮,可能反而降低文字對比。

焦點指示與框線也要和實際相鄰顏色一起檢查。停用控制項雖有 WCAG 適用例外,仍應讓使用者理解狀態。自動產生的值是待驗證的候選色,不是合格證明。

淺色與深色主題可以共用公式

替各主題選擇少量基本色,再共用衍生色的公式:

:root {
  --text: #1f2937;
  --bg: #ffffff;
  --accent: #2563eb;
}
[data-theme="dark"] {
  --text: #e5e7eb;
  --bg: #111827;
  --accent: color-mix(in oklch, #60a5fa, transparent 0%);
}
.card {
  background: color-mix(in oklch, var(--bg), var(--accent) 5%);
  border-color: color-mix(in oklch, var(--text), transparent 85%);
}

深色主題在這裡明確選了另一個強調色。混合 transparent 0% 會保留輸入顏色,並不是把明度反轉。

共用公式能減少重複定義,但不會自動保證每個顏色在兩種主題下都有相同語意。文字、連結、狀態變化及半透明框線,都要在各自背景上檢查。

用 @supports 分開支援功能與備援值

2026 年 9 月 5 日查核的 MDN 相容性資料列出:基本 oklch() 從 Chrome/Edge 111、Firefox 113、Safari 15.4 開始支援;兩色 color-mix() 則從 Chrome/Edge 111、Firefox 113、Safari 16.2 開始。相對色彩語法及更新的擴充功能必須另查,這些版本也不能直接換算成讀者的支援比例。

CSS 自訂屬性可以保留含有未支援函式的值。先寫靜態值、再用同名變數覆蓋,未必能在計算值失效時退回舊值。應把更新放在功能檢測內:

:root { --brand-hover: #3b7ced; }
@supports (color: color-mix(in oklch, red, blue)) {
  :root { --brand-hover: color-mix(in oklch, #2563eb, white 15%); }
}
.button:hover { background-color: var(--brand-hover); }

靜態值是備援色,不保證與計算色完全相同。兩種結果都要搭配文字和背景測試;功能檢測通過,也不代表沒有瀏覽器特有的顯示差異。

Tailwind 的內建色票也需要實際驗證

Tailwind CSS v4 官方色彩定義採用 OKLCH,例如 --color-blue-500: oklch(62.3% 0.214 259.815)。不應把 v3 的整套預設色票一概描述為以 HSL 為基礎。

即使用內建色票,也要檢查實際的前景、背景與狀態組合。採用 OKLCH 不會自動保證廣色域輸出或無障礙符合性。

建議的配色工作流程

  1. 以 OKLCH 定義品牌色,或先轉換已知的 HEX 顏色。
  2. color-mix() 表達候選衍生色。
  3. 在適合時維持相近明度,但不要把 L 當成對比值。
  4. 針對一般文字的 WCAG AA,依適用條件及例外檢查 4.5:1。
  5. 分別選定淺色、深色主題的基本色,驗證全部配對。
  6. 提供靜態備援值,再於 @supports 內更新自訂屬性。
  7. --text-muted--brand-hover 等用途命名,讓設計意圖可被檢查。

產生配色和驗證配色應在同一個流程中完成。新語法或常用色票,都不能取代實際介面的檢查。

重點整理

  • OKLCH 以近似知覺模型描述明度、彩度和色相。
  • color-mix() 能共用衍生色公式,但不保證對比值合格。
  • 分別檢查比例、色相路徑、alpha、背景與色域。
  • 自訂屬性的備援更新應放在 @supports 內。
  • 區分基本語法與擴充功能,並驗證淺色和深色主題。

參考資料與來源

編輯說明

本文使用 AI 協助編輯,並於發布前由編輯確認。內容仍可能包含事實、解讀或時效上的錯誤;進行重要判斷前,請查閱所列的一手資料或官方文件。

相關文章