lch的l值在全色相范围内实现感知亮度一致,而hsl的lightness是rgb最大最小值的算术平均,忽略人眼对波长敏感度差异,导致同值下黄、蓝等色实际cie y亮度差超10倍,ui调色极易失控。

同一L值的lch()颜色在视觉上基本等亮,而hsl()中相同lightness值的颜色亮度差异可达3倍——这不是渲染bug,是HSL数学定义和人眼感知权重根本错位。
为什么hsl(60, 100%, 50%)比hsl(240, 100%, 50%)亮得多
HSL 的 lightness 是 RGB 三通道最大值与最小值的算术平均:(max(R,G,B) + min(R,G,B)) / 2。它完全不考虑人眼对不同波长光的敏感度差异。
- 人眼视锥细胞中,绿敏视锥(~555nm)响应最强,红敏次之,蓝敏最弱——所以同等RGB数值下,绿色通道对“亮度感”贡献远高于蓝色
-
hsl(60, 100%, 50%)(黄)对应 sRGB 值约rgb(255, 255, 0),CIE Y(相对亮度)≈ 0.72 -
hsl(240, 100%, 50%)(蓝)对应rgb(0, 0, 255),CIE Y ≈ 0.07 - 两者
lightness都是 50%,但实际感知亮度差超10倍,UI中用它控制文字可读性必然失效
lch() 的 L 值怎么才算“真等亮”
lch() 的 L 直接映射 CIE 1976 L*a*b* 空间的明度轴,设计目标就是 ΔL = Δ感知亮度差。但它不是无条件可靠的:
-
L必须为 0–100 整数或百分比,lch(50 80 240)合法,lch(0.5 0.8 240)无效(那是oklch()写法) -
L: 0%或L: 100%时,C(色度)强制归零,lch(0 80 240)渲染为纯黑,不是“暗蓝” - Figma 输出的 LCH 默认用 D50 白点,CSS
lch()按 D65 解析,青绿区间色相偏移 3–5°,必须用支持白点转换的工具校准
color-mix(in lch) 混合时亮度塌陷的真实原因
写 color-mix(in lch, lch(80 80 280), lch(30 20 120)) 得到的不是中间调,而是明显偏暗的浊色——问题不在函数本身,而在 L 和 C 的非线性耦合:
- LCH 空间里,固定
L只调h才能保亮度均匀;一旦L和C同时变化,插值路径会经过低感知亮度区域 - 更稳妥的做法是改用
in oklch(Chrome 111+/Safari 16.4+ 支持),它对亮度和彩度做了额外感知校正 - 调试时务必拆开验证:用
oklch(80 80 280)单独输出,确认输入没溢出(如L > 100或C > 150)
深色模式下用hsl()设“暗色”翻车的典型现场
设计师说“按钮禁用态用 hsl(240, 100%, 20%)”,结果在 #121212 背景上几乎看不见——因为它的 CIE Y 实测仅 ≈ 0.01,比同 lightness 的黄色(Y≈0.25)暗25倍。
- 真正可控的做法:先定基准色,转成
lch(),再统一调L值,例如lch(25 60 240)(蓝)和lch(25 70 60)(黄)在视觉上才真属同一“暗度档” - Chrome DevTools 颜色拾取器右键可直接切到
lch()显示,别靠肉眼估或手算 - Firefox 仍需
@supports (color: lch(0 0 0))检测,不支持时降级必须用color-mix(in srgb)或预设变量,不能只靠 HSL fallback
LCH 的 L 值可靠,但前提是它被当做一个**有物理约束的参数**来用:L=0/100 时 C 归零、D50/D65 白点不可混用、混合时 L 和 C 不能随意耦合——这些限制不是缺陷,而是感知均匀性的代价。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











