oklab() 不是 lab() 的补丁而是重写,因其基于 cie 2002 色貌模型重构映射,在蓝紫区消除 lab() 固有非线性失真,l 为 0–1 小数,a/b 无量纲且与 lab() 数值不兼容。

oklab() 不是为了“修复” lab(),而是彻底替换了它——因为 lab() 在蓝紫区域的非线性问题无法靠微调修正,只能换模型。
OKLab 为什么不是 Lab 的补丁,而是重写?
lab() 基于 CIE 1976 L*a*b*,其 a/b 轴在 270°–330°(青→紫→红)段存在固有压缩:小角度变化引发大视觉跳跃,比如 lab(50% 40 -30) 到 lab(50% 40 -40) 看起来不是渐变,而是突然“发灰”或“跳色”。这不是浏览器实现 bug,是数学模型本身在该区域感知失真。
oklab() 放弃了 CIE 1976 的转换公式,改用基于 OKLab 的新映射:它用 CIE 2002 色貌模型重构了亮度与色度关系,在全色相范围内(尤其蓝紫区)保持欧几里得距离 ≈ 感知差异。实测中,oklab(0.5 0.1 -0.1) → oklab(0.5 0.1 -0.2) 过渡平滑无断层。
-
lab()的 b 轴在负值区(蓝/紫)灵敏度坍缩,b=-20 和 b=-30 视觉差远小于 b=+10 和 b=+20 -
oklab()的 b 分量线性响应更均匀,-0.1 到 -0.2 的 Δb ≈ +0.1 到 +0.2 的 Δb - 所有主流浏览器(Chrome 112+、Safari 16.4+)解析
oklab()时直接走新算法,不复用旧 Lab 代码路径
写 oklab() 时最容易被忽略的单位和范围
oklab() 的 L 是 0–1 小数(或 0%–100%),a/b 是无量纲浮点数,但数值含义和 lab() 完全不兼容——oklab(0.5 0.2 -0.1) ≠ lab(50% 20 -10),强行换算会严重偏色。
- L 必须带单位:
oklab(0.5 0.2 -0.1)✅,oklab(50 0.2 -0.1)❌(整数 50 被当 L=50,超出 0–1 范围,整条声明失效) - a/b 虽无硬性上下界,但 Chrome 对 |a| > 0.5 或 |b| > 0.5 的值开始降饱和;Safari 17.5 在 b
- 设计工具导出的 OKLab 值默认用 D65 白点,与 CSS 渲染一致;但若从 Lab 工具转 OKLab,需确认是否已做白点归一化(D50→D65)
为什么你不能靠 oklab() 解决跨设备色差
oklab() 是感知模型,不是设备描述符。它不读取显示器 ICC profile,也不切换色域——浏览器仍以 sRGB 为最终输出基准。所谓“更准”,仅指在标准 sRGB 显示器上,人眼判断颜色过渡是否自然。
- 同一
oklab(0.7 0.15 -0.2)在 P3 屏幕和 sRGB 屏幕上实际发光不同,CSS 不干预 - DevTools 的 computed 样式永远只显示降级后的
rgb()值,看不到 OKLab 中间态 - 想真正控制跨屏一致性,必须搭配
color(display-p3 ...)+@media (color-gamut: p3)条件降级,且 fallback 到 sRGB 值要人工校验
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











