目录
关于 HCL
HCL (Hue-Chroma-Luminance) 与 RGB 一样同属色彩空间的一种,因为最早由国际照明协会 CIE 提出,又被称作 CIELch(uv)。HCL 最普遍应用于程序生成的配色表 (color swatch) 或可视化数据图表配色。在 HCL 色彩空间中,当色相改变而 L 通道保持恒定时,对人眼而言,色彩「对比度」不变。
为什么 HCL 比 HSL 更好?
TL;DR
- HSL 色彩空间中的明度 L 是相对计算机元件而言,而非人眼。L 通道与人眼对明度的感知(Luminance/Relative Luminance,后文以「感知明度」称呼)非线性匹配,HSL 中明度相等的两个颜色,人眼感知到的明度可能相去甚远(参见例子)。但产品的使用者是人类,用色彩进行标识应以人眼感知为准。
- HCL 中只要两个颜色的 L 值(即感知明度)相等,颜色的对比度相等。
- HCL 对颜色识别有障碍的视障人士更友好。即使有障碍,这些人能通过颜色的对比度区分颜色的不同,对比度越强,越容易区分。这里的「对比度」特指感知明度的对比。事实上在 Web 领域里,W3C 的 WCAG2.1 标准中提出了相关的可用性 (accessibility) 要求:文字前景色与背景色要达到一定程度的对比度1。
- 在决定配色阶段使用 HCL 色彩空间取色能够直接控制感知明度,更容易使产品配色达到较高的可用性。
细节
首先澄清几个名词:
- 明度(Lightness):指HSL色彩空间中的 L 通道,简称 L。
- 感知明度(Luminance,在 W3C 中又称为 Relative Luminance):用于量化人眼对光的明度的感知。 HCL 色彩空间中的 L 通道使用的是它,简称Luma。需要与明度区分开来。
- 对比度:两种颜色间感知明度的对比,公式参见下文。
- 色距(Chroma):HCL 中的 C 通道,可以理解为相对饱和度。
相比 HEX 或 RGB,许多设计师和前端工程师喜欢使用 HSL(Hue-Saturation-Lightness) 表示颜色,因为它的可读性更高,能够从数值中直观读出颜色的属性。如同样是三文鱼粉,HEX #fa8072
或 RGB 250, 128, 114
最多只能看出这是一个偏红的颜色, 而hsl(6, 93%, 71%)
可以看出这是一个色相为 6(在色环6°位置),饱和度为 93%,明度为 71% 的颜色。如果要基于这个颜色取补色,只需要对色相数值 +180°为(186, 93%, 71%)
,如果需要取一系列同色系的相近色,只需要对饱和度或明度做细微更改即可,十分方便。
看上去很完美,但 HSL 有个致命的先天缺陷:它是基于 RGB2 模型创造的色彩空间。RGB 中的每个颜色是三色光通过加色法叠加而成——计算机或电视等屏幕的电子元件通过这种方法展示正确的颜色,当元件内一种色光达到极值,而另外两种色光为零时,就发出了正红、蓝或绿色光。但这并不是人眼感知光的方法。因此,HSL中两个颜色如果明度相等,只是对发光元件而言的「相等」。对人眼来说,刺眼程度却大相径庭。举例而言:
虽然亮度都标为 50%,人眼感知正绿 hsl(120, 100%, 50%) 的感知明度为 80%,而正蓝 hsl(240, 100%, 50%) 的感知明度只有 44%,差距达到了 36%。
HCL 中的 L 通道与 HSL 的 L 通道不同,是基于人眼对亮度对感知而创造的。下图解释了人眼对两种色彩空间的色环内颜色的明度是如何感知的(下方灰色部分): HSL 的感知明度是非常不连贯的——讲人话的话就是,你在看左侧黄绿色部分时是不是觉得更刺眼,而蓝紫部分看起来温和多了?而右边色环的感知明度则始终保持连贯,视觉上更舒服。
在实际应用中, HCL 的这一特性可以帮助各色人士更快速、友好地识别不同颜色标识和它传递的信息。
左上图为图表使用的原始配色,均使用了高饱和色,颜色间的过渡无法正确传达信息(紫色到青色代表降雨量增加还是减少了?)。经过去色处理后,也能看出整个图表颜色的感知明度并不是渐变的,时高时低。不仅是视障人士,该图表即使对没有色盲的人群而言也不够直观。
左中是使用了 HCL 理论进行配色的图表,左下方是对颜色进一步降饱和后的版本。颜色渐变暗示的信息更易懂,从右侧的去色图中也能进一步确认颜色间进行了温和过渡,并确保不同颜色的过渡传达出了正确信息。
应用 HCL 到产品配色中
使用辅助工具
事实上,已经有不少帮助你使用 HCL 进行配色的工具存在了。
取色器:
- Work with Color 提供色彩的感知明度值,同时可以在不同色彩空间中做换算
- Color Picker for data
- HCL Wizard
- W3C Working Draft - CSS Color Module Level 4 将提供内置的CSS函数
lch()
选取 HCL 颜色(但目前只是草稿,距离真正能用上再等10年?)
配色设计:
- JS: Safe Color 我自己写的工具,根据提供的前景或背景色随机生成一个符合 W3C WCAG2.1 AA 或 AAA 标准的颜色。可以根据
string
生成固定颜色。 - JS: chroma.js
- Sketch: Chromatic Sketch 基于 chroma.js 的 Sketch 配色插件
- Figma: Chromatic Figma 基于 chroma.js 的 Figma 配色插件
- R: CRAN/colorspace
- Python: colorspace
- JS: Safe Color 我自己写的工具,根据提供的前景或背景色随机生成一个符合 W3C WCAG2.1 AA 或 AAA 标准的颜色。可以根据
可用性检查:
- Chrome 65+ devtools 在取色器里内置了符合 WCAG2.1 AA 与 AAA 标准的前、背景色对比度计算
- color.review 同样提供两个颜色的感知明度对比计算。这是我想做但一直搁置,直到发现有人推出了→_→
- Sketch: Cluse 同样是帮助检查颜色是否达到 AA 或 AAA 标准
硬核派:HSL/RGB 转换为 HCL
由于 HSL 是基于 RGB 色彩模型产生,色彩空间与 RGB 一致。但 HCL 属于另一种色彩空间,两者不一定能完全匹配。具体表现为:转换后颜色但色相、感知明度均存在,但颜色的色距不一定在 HCL 色彩空间范围内。
将 RGB 颜色转换为 HCL 需要通过 sRGB → linearRGB → CIEXyz → CIELab → CIELch,具体转换公式可以查看 W3C 给出的代码。
硬核派:计算 HSL/RGB 的感知明度
⚠️ 前方公式高能,看见公式就头疼的话还是跳过吧。
将 HSL 转换为线性 RGB (linear RGB)
当 0 ≤ H < 360, 0 ≤ S ≤ 1 and 0 ≤ L ≤ 1 时,
参照下表得出 R', G', B'的值:
如果最初是由 8-bit RGB 值转换为 HCL 那么从这里开始,否则无视;
进行校正:
使用线性 RGB 计算颜色的感知明度
计算两个颜色的对比度
其中,分子中的 Luma1 是两个颜色中较浅色的感知明度,分母中的 Luma2 是较深色的感知明度。对比度范围在 1 到 21 之间,通常又写为 1:1 到 21:1。
H 保持不变,由以上可得 H, C, Luma。
延伸阅读
W3C. “How to Meet WCAG (Quick Reference).” How to Meet WCAG (Quickref Reference), 4 Oct. 2019, www.w3.org/WAI/WCAG21/quickref/#contrast-minimum.↩
本文提到的 RGB 色彩空间,均指 sRGB。↩
Bednarz, Etienne. “HCL Utilities.” Art Station, www.artstation.com/artwork/ybGP9x.↩
Stauffer, Reto. “Why HCL.” HCL Wizard, hclwizard.org/why-hcl/. Licensed under Creative Commons Attribution 3.0 Unported License.↩
图片来源: python-colorspace↩