OKLCH本身不定义色域,而是Display P3等广色域上的感知均匀坐标系;其L基于OKLab Stevens幂律校正,映射人眼明暗响应,C经归一化使不同色相饱和度更一致,H在广色域下色相变化更线性,但需配套色域声明与严格降级(oklch→lch→sRGB)才能生效。

OKLCH 本身不定义色域,它只是 Display P3(或 sRGB、Rec.2020)等色域上的“坐标系”——真正变广的是底层色域,OKLCH 只是让这个广色域更可操作、更符合人眼响应。
OKLCH 的 L 不是“亮度值”,而是感知明度
Display P3 色域比 sRGB 多约 30% 色彩,但如果你用 hsl() 或 rgb() 去调一个 P3 蓝色,改 lightness 或 luminance 时,视觉明暗变化会跳变、不均匀——尤其在 20%–60% 区间,人眼对灰阶最敏感,而 HSL 的 L 是线性插值,CIELAB 的 L 有蓝紫压缩。OKLCH 的 L 基于 OKLab 的 Stevens 幂律校正(近似 cube-root),直接映射人眼感知响应。比如 oklch(40% 0.3 240) 和 oklch(50% 0.3 240) 看起来就是“稳稳变亮一档”,不是忽明忽暗。
Chroma(C)在广色域下仍保持语义稳定
在 Display P3 中,绿色和青色能支撑更高的色度值,而红色受限;lch() 的 C 在不同色调下“最大安全值”差异大,容易溢出(浏览器静默裁剪为最近可显色);oklch() 的 C 经过 OKLab 空间归一化,相同 C 值在蓝、绿、红区域的感知饱和度更一致。这意味着:你用 --primary: oklch(60% 0.4 180); --primary-hover: oklch(65% 0.4 180); 写悬停态,不管主色是青是绿,用户看到的都是“略亮一点、饱和不变”,而不是“青变灰、绿爆色”。
和 Display P3 搭配时,Hue(H)角度更可靠
Display P3 的色相边界比 sRGB 更外扩,尤其在蓝紫与黄绿交界区;hsl() 的 H 在这些区域会因 RGB 插值失真,“转一圈”回来颜色不对;oklch() 的 H 是 OKLab 空间中的极角,数学上更平滑,配合广色域设备(如 macOS Ventura+、iOS 17.4+、Chrome 112+)时,H 值变化与人眼观察到的色调偏移基本线性对应。这点在设计系统中做色相渐变(比如从蓝→青→绿)时特别关键——不会中途“跳色”。
立即学习“前端免费学习笔记(深入)”;
兼容性仍是硬门槛,别漏降级
OKLCH 当前仅在 Chrome 112+、Firefox 121+、Safari 17.4+(即 iOS 17.4/macOS 14.4+)稳定支持;旧版 Safari(包括所有 iOS 17.3 及更早)完全忽略整条声明。必须写降级:
color: oklch(60% 0.4 240); color: lch(54% 0.32 240); color: #4a6fa5;
注意三点:① oklch() 必须放在最前;② lch() 降级不能简单复制数值,得用转换工具重算(例如用 Björn Ottosson’s picker);③ 不要指望 oklch() 和 hsl() 数值对齐——它们根本不在同一数学空间里。
真正难的不是写对 OKLCH,而是理解:它不解决“能不能显示广色域”,只解决“怎么在广色域里不翻车”。设备不支持 P3?OKLCH 再准也白搭;写了 OKLCH 却没配 Display P3 的 @color-profile 或 meta 标签?浏览器默认还是当 sRGB 渲染。这些链路断一环,感知优势就归零。


















