oklch() 是构建可访问颜色系统的最可靠底层工具,但需精准控制 L(亮度)、C(色度)和 H(色相):L 必须匹配 WCAG 对比度要求(如主文本深色背景 L 0.85–0.92、浅色背景 L 0.15–0.25),C 在低 L 下需压至 ≤0.12 防溢出,H 应保持稳定;color-mix() 不支持 in oklch,须转 srgb 或 display-p3;@supports 检测必须带单位且写在外部降级色之后;灰色应使用 oklch(L 0 H) 而非 gray();真机多屏测试不可少。

oklch() 本身不自动保证可访问性,但它是构建可访问颜色系统的最可靠底层工具——关键在于用对 L(亮度)和 C(色度),而不是套个函数就完事。
oklch() 的 L 值必须直接对应 WCAG 对比度要求
WCAG 2.1 的文本对比度(AA 级 ≥4.5:1)本质是亮度差的量化。oklch() 的 L 是感知均匀的,0.2 和 0.4 之间的 ΔL ≈ 人眼感受到的明暗差翻倍;而 hsl() 的 l=20% 和 l=40% 在蓝、黄区域视觉差远小于红区。
- 深色背景上的主文本:L 推荐 0.85–0.92(不是“调亮一点”,而是实测对比度 ≥4.5)
- 浅色背景上的主文本:L 推荐 0.15–0.25(纯黑 L≈0.0 会刺眼,且在 OLED 屏上对比度反而过载)
- 禁用态图标/文字:固定 H,C 降到 ≤0.12,L 微调 ±0.02(别只降 L,否则灰得不可读)
- 别信“L=0.5 就是中灰”——oklch(0.5 0 0) 是中性灰,但 oklch(0.5 0.2 120) 是饱和绿,视觉亮度远高于 0.5
color-mix(in oklch, ...) 会静默失效,必须用 in srgb 显式声明
想用 oklch() 基色混合出 hover 态?color-mix() 不接受裸 oklch() 值。浏览器看到 color-mix(in srgb, oklch(60% 0.28 258.5), #000) 会直接丢弃整条规则——它只认色彩空间明确的输入。
- 正确写法:
color-mix(in srgb, color(display-p3 0.145 0.388 0.922) 70%, black 30%)(先转 display-p3 或 srgb,再混) - 更稳妥路径:用 PostCSS 插件(如
postcss-oklab)在构建时把 oklch() 转成 srgb 中间值,再喂给color-mix() - 绝对别写:
color-mix(in oklch, ...)—— 所有主流浏览器当前都不支持该语法,解析失败不报错,只跳过
@supports 检测写错单位,老设备直接变黑块
安卓 WebView、iOS 17.3 及更早 Safari 对 @supports 极其敏感。漏一个 % 或多一个 deg,检测返回 false,整个 OKLCH 块被忽略,fallback 色又没写在外部——结果就是按钮全变黑或透明。
立即学习“前端免费学习笔记(深入)”;
- 降级色必须在
@supports块外、上方定义:button { background-color: #2563eb; }然后才是@supports (color: oklch(0% 0 0)) { ... } - 检测值必须带单位:
@supports (color: oklch(0% 0 0))✅,@supports (color: oklch(0 0 0))❌ - 别用
@supports not—— 部分 WebView 解析崩溃,导致后续所有 CSS 失效 - oklch() 参数必须严格:L 写
60%或0.6(不能混用),C 必须是小数0.28(不是28%),H 不带deg
深色模式切换时,只调 L 值是陷阱,C 和 H 也得约束
很多人以为 “深色模式 = 把所有 oklch() 的 L 从 0.9 降到 0.2” 就完事。实际中,低 L 下高 C 会溢出 sRGB 色域,渲染成意外的灰斑或色偏——尤其青蓝系在 L0.18 就开始失真。
- 安全做法:深色模式下,L 降到 0.2–0.3 后,C 必须同步压到 ≤0.12(比如主色从
oklch(90% 0.28 258.5)→oklch(22% 0.12 258.5)) - H 不建议动:色相偏移会破坏品牌一致性,且跨 0°/360° 边界时插值异常(见渐变段落)
- 灰色必须用
oklch(L 0 H)构建,不用gray()—— 后者在 Safari 17.3 及部分安卓 WebView 中仍不可用 - 测试真机:MacBook Pro(P3)、Dell S2721DGF(sRGB)、iPhone 15(P3)三台设备并排看同一段
oklch(),白点不统一(D65 vs D50)会导致明显漂移
真正难的不是写对 oklch(),而是让 L 值和 WCAG 对比度数字对齐、让 C 值在不同亮度下不溢出、让 @supports 在千奇百怪的 WebView 里不崩——这些细节没卡准,颜色系统就只是好看,不是可用。


















