oklch的l值恒定≠跨色调视觉亮度恒定,必须同时满足单位统一、色相隔离、色彩空间统一、禁用fallback混合四个条件;任一缺失都会导致srgb降级,使oklch(60% 0.28 0)与oklch(60% 0.28 240)出现明暗差。

直接说结论:OKLCH 的 L 值恒定 ≠ 跨色调时视觉亮度完全恒定,必须同时满足四个硬性条件——单位全对、色相隔离、空间统一、禁用 fallback 混合。漏一个,L 再“恒定”也白搭。
为什么 oklch(60% 0.28 0) 和 oklch(60% 0.28 240) 在屏幕上看起来还是有明暗差?
这不是 OKLCH 失效,而是你没切断干扰链路。OKLCH 的 L 确实是感知亮度标尺,但浏览器渲染时会偷偷“降级”: - 如果其中某个颜色是hsl() 或 rgb() 定义的,哪怕只用于 color-mix() 或过渡动画,整条插值路径就会 fallback 到 sRGB
- DevTools 里看到的 computed background-color 永远是降级后的十六进制,根本看不到真实 OKLab 插值过程
- 某些安卓 WebView 对 oklch(60% 0.28 240) 解析失败,但不报错,直接跳过,回退到上一条颜色(可能是黑或透明)
oklch() 中 L 值写错单位会导致跨色调亮度失控
oklch() 对单位极其敏感,错一个字符,L 就彻底失效:
- oklch(60 0.28 240) ❌ —— L 缺 %,Chrome/Safari 静默忽略整条声明
- oklch(0.6 0.28 240) ⚠️ —— 仅 Chrome 112+/Firefox 121+/Safari 17.4+ 支持,且 H 小数位 >1(如 240.543)在部分 Safari 子版本中解析失败
- oklch(60% 0.28 240deg) ❌ —— H 后加 deg,Safari 16.x 及多数安卓 WebView 拒绝识别
- 正确写法只有:oklch(60% 0.28 240) ✅(L 百分比、C 无单位小数、H 纯数字不带单位)
跨色调对比必须用 color-mix(in oklch) 而非 in srgb
想让红(oklch(60% 0.35 0))、蓝(oklch(60% 0.35 240))、绿(oklch(60% 0.35 120))在深色背景上文字可读性一致?不能靠经验调 L:
- 用 color-mix(in srgb, ...) 混合黑白,暗部会发灰紫,尤其红/橙区域亮度感知断崖下跌
- 必须用 color-mix(in oklch, var(--red) 70%, oklch(20% 0 0) 30%) 这类写法,确保 L 值线性衰减,且全程不脱离 OKLab 空间
- 所有参与混合的颜色都得是完整 oklch(L C H) 格式,white 或 black 简写会被忽略
@supports 结构写反会让跨色调恒定彻底失效
很多人把 fallback 写进@supports 块里,结果旧环境连基础色都没有:
- 错误:@supports (color: oklch(0% 0 0)) {
button { background-color: oklch(60% 0.28 240); }
}
- 正确:先写降级色,再包 @supports,且检测值必须带单位:button { background-color: #3b82f6; }
@supports (color: oklch(0% 0 0)) {
button { background-color: oklch(60% 0.28 240); }
}
- 注意:@supports not 绝对禁用——安卓 WebView 解析时可能崩溃整段 CSS
最常被忽略的一点:你在 DevTools 里永远看不到真实的 OKLCH 渲染路径,它只显示最终 fallback 后的 sRGB 值。要验证是否真恒定,只能靠人眼在不同色相间横向扫视,或用 ColorMe 工具逐帧抓取 L 值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











