OKLCH 的 L 值基于感知亮度建模,而 HSL 的 L 是 RGB 极值的算术平均;OKLCH 要求 L 必须带 % 单位,混用色彩空间会导致 sRGB 插值降级。

OKLCH 的 L 值直接对应人眼对明暗的非线性感知,而 HSL 的 L 只是 RGB 通道极值的算术平均——这不是精度问题,是建模逻辑的根本差异。
OKLCH 的 L 是感知亮度坐标,不是数学缩放
HSL 的 L 计算方式是 (max(R,G,B) + min(R,G,B)) / 2,纯属 RGB 立方体上的几何操作。实测显示:hsl(0, 100%, 50%)(纯红)在 CIE Y 明度空间约 0.21,hsl(120, 100%, 50%)(纯绿)约 0.72,视觉亮度差三倍以上;而 oklch(0.5 0.32 0) 和 oklch(0.5 0.32 120) 在 OKLab 空间中落在同一感知亮度层,人眼判断“一样亮”。
这意味着:你调同一个 L 值,HSL 下各色相明暗飘忽不定,OKLCH 下才真正稳定可预期。
单位写错就彻底失效,不是偏色而是消失
oklch() 对 L 的单位极其敏感,浏览器不会报错,只会静默跳过整条声明:
立即学习“前端免费学习笔记(深入)”;
-
oklch(60% 0.28 258.5)✅ —— 兼容性最高,所有支持 OKLCH 的浏览器都认 -
oklch(0.6 0.28 258.5)⚠️ —— Chrome 112+/Firefox 121+/Safari 17.4+ 才支持,旧版 Safari 直接忽略 -
oklch(60 0.28 258.5)❌ —— 缺%,所有浏览器均静默失效
注意:HSL 的 L 写成 50 或 50% 都能解析,但 OKLCH 不行——这是最容易踩的坑,且毫无提示。
混用色彩空间会强制降级到 sRGB 插值
CSS 动画、过渡、渐变不保留色彩空间语义。哪怕你定义了 --primary: oklch(62% 0.28 258.5),只要 hover 状态写成 hsl(240, 70%, 70%),浏览器就会 fallback 到线性 sRGB 插值,中间出现明显灰带或发青。
正确做法只有两个:
- 全链路统一用
oklch(),包括:hover、:disabled、深色模式变体 - 渐变中色相差超过 180°(如
350deg → 10deg)必须手动拆段:linear-gradient(oklch(0.7 0.25 350), oklch(0.7 0.25 0), oklch(0.7 0.25 10))
真正卡住人的从来不是“哪个更先进”,而是你是否验过真机、查过 caniuse、测过降级后按钮是不是突然变透明——OKLCH 的 L 要想接近人眼直觉,前提是你没在单位、混用、拆分这三处掉链子。


















