oklch 的 l 值是感知亮度标尺,直接支撑 wcag 对比度计算;必须用 @supports (color: oklch(0% 0 0)) 检测并前置 fallback,配合 color-mix(in lch) 降级与 font-weight 优化,才能真正控对比度。

OKLCH 本身不解决对比度,但它是唯一能让你“算得准”对比度的色彩空间——所有 WCAG 对比度计算都基于亮度(L)值,而 OKLCH 的 L 就是感知亮度,直接对应公式中的 (L1 + 0.05) / (L2 + 0.05)。
为什么用 oklch() 才能真正控对比度
hsl(240, 100%, 50%) 和 hsl(0, 100%, 50%) 数值上都是 “50% lightness”,但实际 L 值分别是 ≈58 和 ≈27 —— 差一倍。你调 hsl() 的 L,永远不知道真实对比度会崩到哪。oklch() 的 L 是统一标尺:oklch(55% 0.2 240) 和 oklch(55% 0.2 0) 的亮度感知完全一致,差值可直接用于 WCAG 计算。
- 查背景 L 值:用 DevTools 取色 → 粘贴到
ColorMe或浏览器 Color Picker,看 L(如#2d2d2d≈ L:20) - 算文字最低 L:WCAG AA 要求 ≥4.5:1 → 公式为
(L_text + 0.05) / (L_bg + 0.05) ≥ 4.5→ L_text ≥ L_bg × 4.5 − 0.05 × 3.5 ≈ L_bg + 55(经验阈值) - 选色时盯死 L:比如背景 L=20,文字至少设
oklch(75% 0.02 240),不是hsl(240, 0%, 85%)(它 L≈62,不够)
@supports 检测必须写对,且 fallback 必须在块外上方
错一个单位,整条 oklch() 静默失效,文字直接变透明或继承父级色 —— 这是线上对比度“突然不达标”的头号原因。
- 检测语法必须是
@supports (color: oklch(0% 0 0)):L 带 %、C 是小数、H 无单位,缺一不可 - 绝对禁用
@supports not (color: oklch(0% 0 0)):安卓 WebView 解析崩溃整块 CSS - fallback 必须写在
@supports块**外部且上方**:color: #e0e0e0;放第一行,@supports块放第二行;颠倒顺序会导致 Chromium 跳过 fallback - fallback 颜色只能用老浏览器认的格式:
rgb(224, 224, 224)或hsl(210, 10%, 83%),不能用#e0e0e080(hex alpha 不被识别)
用 color-mix(in lch) 动态微调,但必须加降级
静态配色易漏配深色模式、P3 屏、高对比设置等场景。color-mix() 在 lch 空间里线性混合,能保证提亮/压暗后 L 值可控,但旧版 Safari 完全不支持。
- 正确写法:
color: #e0e0e0; color: color-mix(in lch, white 85%, var(--bg) 15%);—— 第二条覆盖第一条,且只在支持环境生效 - 混入比例控制在 5%–15%:超过 20% 会明显削弱对比,低于 5% 几乎无变化
- 不能用
in srgb:sRGB 插值非线性,中间帧发灰,L 值不可预测 - 如果
--bg是渐变或图片,currentColor失效,得用 JS 读取getComputedStyle(el).backgroundColor后注入 CSS 变量
小字号文字必须同步调 font-weight 和抗锯齿
再准的 OKLCH L 值,在 OLED 上 font-weight: 400 + ≤14px 也会泛青、毛边 —— 对比度数值达标,但人眼感知崩了。
- 正文最小字号 ≥14px 时,
font-weight: 500起步;按钮/标题建议600或更高 - OLED 设备加
-webkit-font-smoothing: antialiased抑制子像素镶边 - 加
text-rendering: optimizeLegibility启用字距优化(Chrome/Firefox 支持) - 禁用
font-smooth: always:已废弃,无效
OKLCH 的 L 值不是“百分比亮度”,而是感知标尺;写错单位就失效,不报错也不警告;color-mix() 再好,没降级就是生产事故;小字号不调 weight,对比度数字再漂亮也白搭。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











