- 原文地址:A Guide To Modern CSS Colors With RGB, HSL, HWB, LAB And LCH
- 原文作者:Michelle Barker
- 译文出自:掘金翻译计划
导读:你知道你所选择的配色会影响到你的网站所消耗的电量吗? 仅仅是选择更加环境友善的颜色甚至就能降低对移动设备电池寿命的影响。在这篇文章中,Michelle Barker分享了一些建议,有关于现今在处理CSS色彩时你必须记住的浅规则。 网页色彩远比你所看到的要更复杂,且更有趣!今天,我们将一览在设计系统中使用色彩的最佳方式,与色彩能带来的效果。
大家所熟知的色彩值
在CSS中有很多方式可以定义颜色。
CSS中已赋名的颜色是为元素添上色彩的其中一个最简易的方法:
.my-element {
background-color: red;
}
这是一个非常侷限、且很难贴合我们设计的方法;我们也能使用hex色码(十六进制色彩码),例如这个色彩码为我们的元素添上了红色背景:
.my-element {
background-color: #ff0000;
}
除非你是一名色彩学专家,否则色彩码非常难以阅读;你不太可能光靠色彩码就猜出元素的颜色。当我们在建构网站时,设计师可能会交给我们一份hex色码,但当他们要求我们产生一个"变暗20%"的色彩码,在没有视觉协助或颜色选择器的情况下,调整色彩码对我们来说将非常困难。
RGB
RGB (红、绿、蓝)表色法是一个编写颜色的替代方案,让我们能够以更容易阅读的方式使用与hex色码同样范围的颜色。在CSS中,我们有一个rgb()函数(function)能够使用。
网页的色彩是加法的,意思是当红、绿、蓝部分的数值越高,颜色就会变得越亮。如果我们只使用红色信道,结果将是红色:
.my-element {
background-color: rgb(255, 0, 0);
}
将红、绿、蓝信道全部设为最高值会变成白色:
.my-element {
background-color: rgb(255, 255, 255);
}
我们也能增加一个alpha信道(供透明度使用),即为rgba() 函数:
.my-element {
background-color: rgba(255, 0, 0, 0.5); // 50%透明度
}
.my-element {
background-color: rgba(255, 0, 0, 1); // 完全不透明
}
rgb() 与 rgba() 让我们更好的使用色彩,但其结果可能有些无法预测。
HSL
最近,我们开始能够透过hsl() 与 hsla() 色彩函数来使用HSL(色相、饱和度、亮度)了。作为一名开发者,这是一种能更加直觉地调整颜色数值的方法。举例来说,我们可以通过调整lightness(亮度)的参数来获得相同颜色下更暗与更亮的版本。
.my-element {
background-color: hsl(0deg, 100%, 20%); // 暗红
}
.my-element {
background-color: hsl(0deg, 100%, 50%); // 正红
}
.my-element {
background-color: hsl(0deg, 100%, 80%); // 亮红
}
hue(色相)参数代表颜色在色环上的位置,可以是0到360deg(360度)范围内的任意值。此函数也能够接受以turn作为单位(如0.5turn)与无单位的值。
下列皆有效:
.my-element {
background-color: hsl(180deg, 50%, 50%);
}
.my-element {
background-color: hsl(0.5turn, 50%, 50%);
}
.my-element {
background-color: hsl(180, 50%, 50%);
}
贴士:在Chrome与Firefox开发工具中可以在style里找到元素的颜色,按住SHIFT并点击一下颜色方块,就可以在hex、RGB与HSL的数值之间切换了哦!
hsl()与hsla()也非常适合使用自定义属性进行操作,请见下一段。
currentColor
值得一提的关键字currentColor能够为已存在的元素设置颜色,它允许我们有效率地使用元素的当前文本颜色作为变量。这通常用于设置SVG图标的填充颜色,以确保它们能匹配其父级元素的文本颜色,详见此处。
现代色彩语法
CSS Color Module Level 4 提供了我们更方便的色彩函数语法,并拥有浏览器的广泛支持。数值不再需要用逗号隔开,而rgb()与hsl()函数能选择性的使用alpha属性,只需要用斜线隔开即可:
.my-element {
/* 选择使用50%不透明度 */
background-color: hsl(0 100% 50% / 0.5);
}
.my-element {
/* 没有alpha属性即完全不透明 */
background-color: hsl(0 100% 50%);
}
新的CSS色彩函数
HWB
HWB代表色相、白值与黑值。就像HSL,色相值的范围在0到360之间。另外两个参数则控制多少白或黑被混合进该色相中,最高到100%(将导致纯白或纯黑);而如果白值与黑值相等地混入,颜色会变得越来越灰,就如同混合颜料一样。这在制造同色系色彩时相当有用。

在这个 demo上试试看吧(只在Safari中运作): 在Pen上的HWB color (Safari only) by Michelle Barker。
LAB
LAB和LCH在这篇技术规范 中被定义为独立于设备的色彩函数。 LAB的色域能够通过如Photoshop类型的软体查看,并且很适合使用在"当你想将萤幕上的那个颜色印在T恤"的场景中。它使用三个轴:亮度、A轴(绿到红)、B轴(蓝到黄)。
它的亮度用百分比表示,挺像 HSL,但在使用lab()色彩函数时可以超过100%。特别亮的白色最高可以使用到400%。_a_和_b_轴的值可以从正数到负数。两个负数的值会让颜色光谱偏向绿/蓝端,同时两个正数值能让色相更加橘/红。
.my-element {
background-color: lab(80% 100 50); //浅粉色
}
.my-element {
background-color: lab(80% -80 -100); //蓝绿色
}

在Pen上的LAB Color (Safari only) by Michelle Barker.
LCH
LCH代表亮度、色度、与色相。就像LAB,亮度是能超过100%的百分比值。而就像HSL,色相的值介于0到360之间。色度代表颜色的量,我们可以把它想像成 HSL的饱和度,但色度的值可以超过100——事实上,它的理论值没有上限。使用范例:
.my-element {
background-color: lch(80% 100 50);
}
.my-element {
background-color: lch(80% 240 50); //这个颜色将超过现今浏览器能显示的值域
}
然而,现今浏览器与显示器可以显示的颜色是有限的(稍后会详细介绍),因此230以上的值已经几乎没有差别——色度将会被降低直到在显示范围内。

最右端的颜色已经超过显示范围(色域),所以我们感觉不到差别。
当我们有了HSL,为什么还需要LAB和LCH?其中一个原因是:LAB和LCH让我们能够使用更大范围的色彩,也就是整个人类视觉能看见的光谱范围。此外,HSL和RGB也有一些缺点:它们在感知上并不统一,且在HSL中,根据色调的不同,增加或减少亮度会产生完全不同的效果。
在这个demo中,透过点击灰度按钮,我们可以发现LCH和HSL之间的鲜明对比。即使元素的HSL函数相同,我们还是能感觉到HSL的色相与饱和度条上每个方块的感知亮度有明显差异!同时,LCH的色相与色度条却拥有几乎一致的感知亮度。

通过使用灰度过滤器,我们可以发现当我们调整色度和色相时,LCH 颜色(图左侧)具有几乎均匀的亮度,而在调整 HSL 颜色(图右侧)的色调和饱和度时有明显的亮度差异。
我们在使用LCH做渐变时也可以发现很大的不同。这两种渐变都以同样的颜色开始和结束(请使用此 转换器 将LCH值转换为同等的HSL值),但LCH的渐变在中间段转变为明亮的蓝色和紫色,而HSL渐变看起来则更为浑浊且褪色。

尽管LAB和LCH在语法上不太直观,其颜色的表现形式却能让人眼更好地理解。在这篇文章:CSS中的LCH颜色三问中, Lea Verou向我们详细地解释了 LCH的好处。同时她也写了一个LCH颜色选择器可供使用。
此外其他色彩函数,如hwb()、lab()、lch(),也有提供可选择的alpha参数。
.my-element {
background-color: lch(80% 240 50 / 0.5); //将呈现50%透明度
}
色域与浏览器支持
近期支持hwb()、lab()与lch()的浏览器仅有Safari,但我们仍可以退一步使用不支持的浏览器。不支持这些函数的浏览器会直接忽略第二条规则:
.my-element {
background-color: lch(55% 102 360);
/* 使用Lea Verou的工具将LCH转成RGB: https://css.land/lch/ */
background-color: rgb(98.38% 0% 53.33%);
}
如果有些样式支持新的颜色函数,我们可以使用特色查询:
.my-element {
display: none;
}
/* 只在浏览器支持lch()时显示这个元素 */
@supports (background-color: lch(55% 102 360)) {
.my-element {
display: block;
background-color: lch(55% 102 360);
}
}
值得注意的是,就像 Lea在她的文章中所解释的,虽然现代萤幕能够显示超越RGB的颜色,但大部分浏览器目前仅支持在sRGB色域中的颜色。在LAB范例中,你可能有注意到将滑杆移动到某些特定的点之外时颜色就不再有变化,即使是在支持lab() 与lch()的Safari上也一样。这是因为超过sRGB色域的颜色只在硬体与浏览器都足够进步时才有影响。
Safari现在已经支持color()函数让我们能在P3色域中显示颜色,但现在只限制于RGB颜色,还未能让我们发挥LAB与LCH的优势。
.my-element {
background: rgb(98.38% 0% 53.33%); // 亮粉色
background: color(display-p3 0.947 0 0.5295); // P3色域中的相同颜色
}
推荐阅读:CSS中的P3广色域 by Nikita Vasilyev
便利性
一旦LAB与LCH得到广泛支持,或许将可以帮助我们更轻松的选择颜色组合。前景文本与背景色在不同的色相或色度之下应该具有相同的对比度,因为它们的亮度始终不变;但目前使用的HSL显然不是这种情况。
色彩管理
更多的色彩函数意味着我们在应用中管理色彩时有更多选择,毕竟在我们的设计系统中经常需要给定颜色多种由浅到深的变体。
自定义属性
CSS的自定义属性允许我们储存数值以在样式表中重复使用。由于它允许使用部分的属性值,因此在管理与操控颜色值上特别有用。HSL的直观性导致它特别适合自定义属性,在之前的范例中,我们通过计算基于元素索引值的--hue值(已在另一个自定义属性中被定义)调整每个颜色条中每个片段的色相。
li {
--hue: calc(var(--i) * (360 / 10));
background: hsl(var(--hue, 0) 50% 45%);
}
我们也可以计算互补色(色环两端的颜色)。这方面的文章已经有很多了,所以我不会再介绍它,但如果你很好奇,那幺 Sara Soueidan的文章HSL的色彩管理是一个很好的起点。
从HEX/RGB到HSL
RGB色能在一定程度上满足您的需求,但如果您需要灵活地从基础颜色搭配中获得新色调,那么您最好换到HSL(或LCH,一旦它被支持)。我建议您为此采用自定义属性。
**备注:**有很多在线资源能将hex或RGB值转换为HSL(例如这个)。
若您的颜色存储形式为Sass变量:
$primary: rgb(141 66 245);
当我们转换为HSL,我们可以为色相、饱和度和亮度值分配自定义属性。这让我们在创建更暗或更亮、更多或更少饱和的颜色变体时变得容易。
:root {
--h: 265;
--s: 70%;
--l: 50%;
--primary: hsl(var(--h) var(--s) var(--l));
--primaryDark: hsl(var(--h) var(--s) 35%);
--primaryLight: hsl(var(--h) var(--s) 75%);
}
正如Adam Argyle在文章建构配色方案中所述,HSL在创建配色方案上非常有用。文中他以品牌形象色为基础,创建了浅色、深色和朦胧的配色方案。我很喜欢这种方法,因为它允许我们对颜色变体做一些细微的调整(例如降低饱和度),但仍保留自定义属性的优势:一键更新所有配色方案,这将会在未来为我们节省大量工作。
SASS色彩函数
一直以来Sass提供了颜色函数让我们能混合和调整颜色。我们可以使其饱和或去饱和,变亮或变暗,甚至将两种颜色混合。它在某些情况下效果很好,但却有一些限制:首先,我们只能在编译时使用它们,而不能实时在浏览器中操作颜色。第二,它们只能使用RGB和HSL,因而面临着相同的感知单一性问题,正如我们在这个范例中所见,当颜色越来越不饱和,在转成灰阶时却越来越亮。

上端的颜色条使用了灰阶过滤器。随着我们降低Sass的主要红色饱和度(下端),我们可以发现颜色事实上变得更亮了。
为了确保亮度保持一致,我们可以用类似HSL的方式在 LCH中使用自定义属性。
li {
--hue: calc(var(--i) * (360 / 10));
background: lch(50% 45 var(--hue, 0));
}
颜色混合与操控
颜色混合
CSS尚不允许我们在浏览器中混合颜色,但这一切即将改变:第5级CSS色彩规范(草案)包含了相当有发展性的颜色混合函数提案。第一个是color-mix()函数,它以类似于Sass mix() 函数的方式混合两个颜色。但是CSS中的color-mix()允许我们指定色域,并默认使用 LCH,因此混合效果拔群。
更新:color-mix()与color-contrast()已经出现在Safari 15的一个标记中!阅读这篇文章以了解如何启用Safari的实验功能。
作为参数传入的颜色不必是LCH,但此插值将使用指定的色域。我们可以指定每种颜色的量来混合,类似于渐变停止的地方:
.my-element {
/* 等量的红与蓝 */
background-color: color-mix(in lch, red, blue);
}
.my-element {
/* 30%红,70%蓝 */
background-color: color-mix(in lch, red 30%, blue);
}
色彩对比与便利性
color-contrast()是另一个被提出的函数,而此函数对选择能使用的颜色有巨大的影响。事实上,它在设计时首先考虑的就是可用性。它允许浏览器通过与另一种颜色进行比较来从列表中挑选出最合适的值。我们甚至可以指定想要的对比度,以确保我们的配色方案符合 WCAG 准则。颜色将被从左到右地评估,而浏览器将从列表中选择第一个符合所需比例的颜色。如果没有颜色符合比例,则将选择对比度最高的颜色。
.my-element {
color: wheat;
background-color: color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA);
}
由于现在没有任何浏览器支持这个函数,我直接从规范中借用了这个例子。当浏览器评估上面的表达式时,结果将是深绿色(darkgreen),因为与文本的小麦色(wheat)相比,它是第一个满足AA对比度的颜色。
浏览器支持
第5级色彩规范目前仅是草案,意味着没有浏览器能支持the color-contrast()与color-mix(),且他们的语法在未来可能会有变化。但它们显然预示着网页色彩的光辉未来!
颜色对环境的影响
你知道你所选择的配色会影响到你的网站所消耗的电量吗?在OLED屏幕上(大多数现代电视和笔记本电脑都在使用),暗色所消耗的电量远远低于浅色——白色耗电最多,而黑色最少。依据可持续网页设计的作者Tom Greenwood的说法,相较于光谱中红色与绿色的区域,蓝色也更加耗能。为了减少您应用程序对使用环境的影响,请考虑使用更深的配色方案,减少使用蓝色,或让您的用户能够拥有黑夜模式。此外,更加环境友善的颜色甚至能降低对移动设备电池寿命的影响。
推荐工具
Hexplorer, Rob DiMarzo 透过互动可视化网页学习理解hex颜色。
LCH color picker, Lea Verou and Chris Lilley 获取LCH颜色与对应的RGB颜色。
HWB color picker 可视化HWB颜色,并转换为HSL、RGB和hex。
Ally Color Tokens, Stephanie Eckles 一个可用的色码生成器。
资源
“书呆的网页颜色指南,” Sarah Drasner, CSS-Tricks
“CSS中的LCH颜色三问,” Lea Verou
“谁是CSS中最好的色彩函数?,” Chris Coyier, CSS-Tricks
“建构配色方案,” Adam Argyle, Web.dev
“使用CSS中的HSLwww.smashingmagazine.com/2021/07/hsl… Ahmad Shaheed, Smashing Magazine
“从Hex与RGB切换成HSL,” Sara Soueidan
“改善网页色彩,” Dean Jackson, Webkit Blog