#FFFF00 的纯黄和 #0000FF 的纯蓝,在 HSL 里的亮度参数完全相同,都是 50%。可人眼看到的却是另一个故事:按相对亮度公式算,黄色的 0.2126+0.7152=0.9278,蓝色只有 0.0722,相差近 13 倍。两个模型都没错,错的是把它们当成同一套「亮度」语言。选哪个,取决于你在跟屏幕的物理打交道,还是跟人的眼睛打交道。
RGB 是设备的原生语言
RGB 三元组是显像管三支电子枪的直接报表:(231,76,60) 意思是红通道开 231、绿 76、蓝 60,像素该发多少电子写得明明白白。它是硬件、图片和设计稿的物理真值,可是一种「坐标式」的表述,和感知无关:把 R 从 231 改到 200,颜色究竟变了多少、会偏橙还是偏粉,数字本身不回答,人只能瞎猜。让程序用 RGB 做「调亮一点」这类语义操作,等于让地图经纬度去理解「往东边的感觉」。
HSL 把颜色翻译成人话
HSL 的三个轴对应人描述颜色的三种口癖:H 色相是色相环上的角度(0 红、120 绿、240 蓝),S 饱和度是「颜色浓不浓」,L 亮度是「离黑离白多远」。从 RGB 换算有固定公式:L 等于最大通道与最小通道的均值,比如 #E74C3C 的 max 231、min 60,L=(231+60)/2=145.5,除以 255 得 57%;亮度过半时 S=(max−min)/(510−max−min)=171/219≈78%;H 按最大通道落在哪段来算,红色段用 60°×(G−B)/(max−min)=60×16/171≈6°。这个颜色的人话版:色相环 6 度、浓、偏亮——三句话就锁死了。
按任务选:修图用 HSL,交差用 RGB
需要「语义操作」时 HSL 完胜:基于品牌色生成 hover 态,L 从 57% 降到 47% 就是暗一档;做禁用态,S 拉到 30% 自然发灰;从一主色生成 12 色循环盘,H 每次加 30° 即可。反过来,最终交付必须回到 hex 或 rgb 函数——CSS 的 rgba、Canvas 的 fillStyle、图片文件全都按通道存储;而且改通道不等于改观感:把 (231,76,60) 三通道同乘 0.82 得到的「暗」是电子强度的暗,人眼对亮度近似开平方地敏感(伽马特性),实际观感暗得比预期少,同样目标在 HSL 里动 L 反而听话。
HSL 的坑:L 不是真亮度
回到开头的反例。人眼亮度权重 Y=0.2126R+0.7152G+0.0722B(通道归一化后),对绿色近乎偏爱、对蓝色近乎失明。#00FF00 与 #FF0000 的 L 都是 50%,感知亮度却是 0.7152 比 0.2126,差 3.4 倍;#FFFF00 同样 L=50%,实际 0.9278 接近白的亮度。后果很具体:用 L 参数做「均匀阶梯」的图表配色,蓝色台阶会肉眼发闷,黄色台阶会抢眼炸屏。对感知一致性要求高的可视化,得换 LAB 或更现代的 OKLCH,那些模型的明度轴才是照着人眼标定的。
一条实操路线
工程上常见的分工:定义设计系统时用 HSL 存主色和派生规则,改一处滑块整套配色跟着动;落地到样式表时输出 hex 或 rgb,兼容性最稳;做数据可视化排序明暗时,别信 L,按亮度公式给每个颜色算 Y 再排。在 颜色转换工具 里同一个色值可以在 RGB、HSL、hex 之间来回切,上面 6 度、78%、57% 这两个数贴进去就能当场复核对不对得上。选模型的准则其实就一句:离人眼近的操作用 HSL,离屏幕近的交付用 RGB。