约 7 分钟读完 · 更新于 2026-10-21 · 文中每条都能在下面的配套工具里动手验证
HEX 和 rgb() 描述的是 sRGB 色域里的点——1996 年为 CRT 定的标准,只覆盖人眼可见范围的一小部分。现代手机与显示器普遍支持 display-p3,饱和的红绿青比 sRGB 多出近三分之一。你写的 #22c55e 在 p3 屏幕上被硬映射,在别的设备上就显得不一样;而 OKLCH 把「颜色」与「设备能力」解耦:L 明度、C 色度、H 色相都按人眼感知均匀刻度。
| 分量 | 含义 | 比 HEX 好在哪 |
|---|---|---|
| L 明度 0–100% | 感知明度,L 相同的两个颜色看起来一样亮 | 等明度色阶终于「真的等明度」,HEX 做不到 |
| C 色度 0–0.4+ | 饱和度,但沿感知刻度 | 降饱和不再顺带变亮/变暗 |
| H 色相 0–360 | 色环位置,与 sRGB 色相角不同 | 蓝紫方向不会再「转一下就变色」 |
CSS Color 4 的正确姿势:@supports 里写 p3 增强,外层保留 sRGB 回落;再用 color-gamut 媒体查询判断设备能力。色值超出目标色域时浏览器会裁剪(gamut mapping),但主动控制比被动裁剪可控得多。
.brand {
color: oklch(64% 0.2 262); /* 全浏览器:OKLCH 语法 */
}
@media (color-gamut: p3) {
.brand { color: oklch(64% 0.28 262); } /* p3 屏:更高色度 */
}
/* 极老浏览器连 oklch() 都不认 → 再补一行 hex 放最前 */--brand-50: oklch(97% 0.03 262); --brand-500: oklch(64% 0.21 262); --brand-900: oklch(32% 0.12 262); /* L 从 97 线性降到 32,视觉上每级亮度差一致。 用 HEX 手调的 #eef→#123 色阶明度忽高忽低。 */
2023 年起全绿:Chrome 111、Safari 15(部分 16.4)、Firefox 113。2023 年之前的浏览器会丢弃整条声明,所以把回落 hex 写在前面仍然是标准做法。
HSL 的「明度」不是感知明度:hsl(60 100% 50%) 的黄色看起来远比 hsl(240 100% 50%) 的蓝亮,调 L=50% 得到的颜色亮度天差地别。OKLCH 的 L 是按人眼响应标定的,L 相同等亮——这就是 Tailwind v4、iOS、Figma 都转向 OKLCH/OKLab 的原因。
取决于色相:绿青方向 sRGB 大约 0.15+ 就出界,红紫方向能到 0.25+。别背表——用转换工具的色域标尺看实时判定,溢出时会给出 sRGB 内最接近的可视替代。