问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

CSS颜色表示法完全解析:从RGB到OKLCH

创作时间:
作者:
@小白创作中心

CSS颜色表示法完全解析:从RGB到OKLCH

引用
CSDN
1.
https://blog.csdn.net/frgod/article/details/144278918

CSS中的颜色表示法多种多样,从传统的RGB、十六进制到更现代的HSL、HWB,再到支持广色域的LAB、LCH等,每种表示法都有其独特的优势和适用场景。本文将详细介绍这些颜色表示法的工作原理、使用场景以及它们之间的相互关系,帮助读者更好地理解和使用CSS中的颜色。

CSS 颜色表示法简介

CSS目前支持多种颜色表示方法,包括rgb()hsl()函数表示法等。这些函数在各种浏览器中都得到了很好的支持。另外还有一些新的表示法尚未得到很好的支持,例如hwb()lab()lch()oklab()oklch()等等。这些颜色表示方法也是直到2022年年末至2023年6月前后才陆续添加到浏览器中。截止到2024年6月前后,启用这些颜色表示法可能还需要定义回退值才妥当;不过随着浏览器的逐步升级,这些新的表示法也将逐渐推广普及。想了解最新的浏览器兼容情况,可以查看Can I Use网站发布的最新数据:https://mng.bz/EZKo。

RGB 与十六进制颜色表示法

十六进制颜色表示法分别规定了红、绿、蓝三原色的取值,且每种颜色分量都用两位数的十六进制数值来表示,取值范围介于00到FF之间。十六进制是一种以16为基数的数字系统,十到十五的数值分别用字母A到F表示。例如颜色#80c090表示红色80、绿色c0、蓝色90(相当于十进制下的红色128、绿色192和蓝色144)。

新版的八位十六进制表示法还包括了另外两位数,用于表示α通道(alpha channel)值,即透明度的大小。该值的取值范围同样介于00(即完全透明)到FF(即完全不透明)。因此,#80c09088其实是颜色值#80c090的半透明版本。

注意:十六进制表示法有时也可以简写为三位数,其中每位数字都各重复一次(doubled)。例如,#c90等效于#cc9900。此外还有一种对应的四位数表示,可以通过类似处理扩展为带α值的八位十六进制颜色值。

rgb()函数则是一种使用十进制数而非十六进制数来描述颜色的方法。其各颜色分量的取值范围不再是十六进制下的00到FF,而是对应的0到255。例如rgb(0 0 0)表示纯黑色(等效于#000);rgb(136 0 0)则表示砖红色(等效于#800)。

RGB与十六进制表示法仅适用于sRGB色域标准。无论是RGB表示法还是十六进制表示法,理解起来都有点费劲。我们见到一个颜色值,例如#2097c9,或者它对应的RGB颜色,无法联想到它在页面会渲染成什么样。如果尝试分解一下,它的红色值(20)将非常少,绿色值(97)为中等水平,蓝色值(c9)则相对偏高。经分析得出,该颜色的蓝色和绿色占主导,但是颜色有多深呢?又有多鲜艳呢?都说不准。事实上,RGB颜色表示法很不直观,它们本来就是方便计算机读取的,并不适合用肉眼识别。

十六进制颜色表示法只有当需要某种书写简洁、且可以方便地在不同应用程序之间复制粘贴颜色值时才有一席用武之地;而RGB表示法同样问题多多,和十六进制法相比妥妥的令人费解有余而方便简洁不足。然而其他大部分颜色表示法都比它们更加好懂且易用。

HSL 颜色表示法

HSL则是一种更适合人类读取的颜色表示法,其名称分别代表色调(Hue)、饱和度(Saturation)和亮度(Lightness)。HSL的语法形如hsl(198deg 73% 46%),相当于十六进制下的#2097c9。

HSL中,代表色调的第一个参数其实是一个角度值,取值范围介于0度到359度之间。它代表色相环1上的度数,可以从红色(red,0度)依次过渡到黄色(yellow,60度)、绿色(green,120度)、青色(cyan,180度)、蓝色(blue,240度)、洋红色(magenta,300度),然后再回到红色。此外,角度取值范围以外的值仍然是有效的,并可通过加减360度来找到等效的色相环上的色调值。书写时也可以省略角度单位deg,直接写成一个数字。

HSL表示法的第二个参数代表饱和度,是一个代表颜色强度的百分数:值为100%时颜色最鲜艳;为0%则意味着没有彩色,仅呈现一片灰色。

HSL表示法的第三个参数表示亮度。它也是百分数,用以描述颜色的明暗程度。大部分鲜艳的颜色采用的是50%的亮度值,且亮度值越高,颜色越浅,浅至100%时就变成了纯白色;而当亮度值越低,颜色越深,深至0%就变成了黑色。

再比如,hsl(198deg 73% 46%)这个颜色值,其色调为青蓝色,饱和度相当高(73%),而亮度接近50%,因此会产生一个比天蓝色更深一些的蓝色。HSL颜色表示法也只适用于sRGB色域标准。

提示:一种更新的、不使用逗号的颜色函数表示法

在CSS首次引入RGB表示法和HSL表示法时,rgb()hsl()颜色函数在使用时必须用逗号分隔每个参数,不能写作rgb(136 0 0),而必须写作rgb(136, 0, 0)。为了向下兼容,这些颜色函数继续保留用逗号分隔的写法;而对于其他新推出的颜色函数就只支持不带逗号的写法。因此推荐使用无逗号写法,这样所有浏览器都支持该语法。

rgb()hsl()也有相应的rgba()版本和hsla()版本,这些扩展函数可以接受第四个参数来设置代表颜色透明度的alpha通道值。现在已经不用再写这些扩展函数了,因为新版语法也支持写在斜线后的alpha参数设置。例如,rgb(136 0 0 / 0.7)定义了一个不透明度为70%的砖红色(brick red)。后续介绍的所有颜色函数都支持通过这种方式设置的不透明度。

HWB 颜色表示法

HWB表示色调(Hue)、白度(Whiteness)和黑度(Blackness)。例如,某颜色利用该表示法可以写作hwb(198deg 12.5% 20.4%)。它其实等效于之前介绍过的用HSL表示法描述的那个深蓝色。

HWB颜色表示法中的色调值等同于HSL表示法中的色调值;同样,它既可以写成一个角度值,也可以直接写成一个数字。

HWB表示法中的W值和B值均为百分数,分别用于描述该颜色混入了多少白色或黑色。如果两个值都偏低,那么最终颜色就会更鲜艳。

hwb(0deg 100% 0%)即为纯白色(此时的颜色与色调无关);而hwb(0deg 0% 100%)则为纯黑色;如果W和B之和大于或等于100%,则最终颜色将为纯灰色,其深浅程度取决于二者中取值更大的一方。HWB表示法同样仅适用于sRGB色域标准。

新一代色彩空间

接下来的四种颜色表示法适用于广色域色彩空间(wide gamut color spaces)。这些表示方法不局限于sRGB色域或其他任何色域,而是能够代表人眼所能看到的任何颜色。换句话说,它们甚至可以描述超出硬件能力边界的颜色。在这种情况下,浏览器会自动将这些颜色做圆整处理,并归入最接近的可用色域范围内——只要不超出预期的取值范围,通常就能得到可接受的备选颜色。比如,可以利用这个原理来指定P3色域下的颜色,对于不支持P3色域的显示器而言,用户最终看到的将是最接近该颜色的sRGB色域下的近似值。

这些颜色表示法的另一个好处在于,它们力求在色彩感知上做到线性展示。也就是说,其颜色值是根据我们人类的感知来定制的。例如,在HSL体系中,亮度为50%的绿色会比同等亮度下的蓝色看起来更亮一些,因为我们的眼睛会认为绿色更亮;而在新一代色彩空间中,色彩是均衡的(balanced),因此相同亮度的所有色调对我们的眼睛而言都是一样的。同理,在控制色彩鲜艳度的数值上也是如此。

LABLCH是其中最先创建的两种颜色表示法,但它们的规范尤其是在一些蓝色和紫色的色调方面还存在一些与规范不一致的地方,因此其表现也差强人意。后来OKLABOKLCH表示法取代了它们。新方法在概念上类似,但行为上可预测性更强。虽然接下来我将分别介绍这四种颜色表示法的工作原理,但还是强烈推荐使用OKLABOKLCH表示法。浏览器对以上四种表示法的支持情况也几乎完全相同。

LAB 和 OKLAB 颜色表示法

LAB颜色及其后续版本OKLAB都定义了三个维度值:亮度、A轴(A axis)与B轴(B axis)。其语法格式形如lab(58% -19 -35)或者oklab(65% -0.06 -0.1)。虽然二者的数值不同,但在概念上都是相同的。

第一个参数,亮度,是一个值域介于0%(即黑色)到100%(白色)的百分数。在LAB表示法中,也可以使用0到100间的数字来表示;而在OKLAB中,还可以写成0到1.0之间的数字。鉴于这种写法上的差异可能引起混淆,推荐还是使用百分数为上。

而A轴的取值范围介于红色到绿色;B轴则介于蓝色到黄色。在OKLAB中,这些值的具体范围分别是-0.4到0.4(也可以使用-100%到100%之间的百分数来表示)。而在LAB中,上述值的值域则为-125到125。

LABOKLAB都是矩形色彩空间,类似于RGB的广色域版本;但与RGB类似,它们使用起来都不是很直观。

LCH 和 OKLCH 颜色表示法

LCHOKLCH则是与HSL相似的圆柱形色彩空间(cylindrical color spaces)。它们定义的是这三个维度值:亮度(Lightness)、色度(Chroma)和色调(Hue),语法上则可以写作lch(58% 39.8 241.5deg)以及oklch(64% 0.12 233deg)

提示OKLCH这个名字有点拗口。Web开发者埃里克·波蒂斯(Eric Portis)首创了 “Oklachroma” 这个词来作为OKLCH的一种更为友好的发音方式,别说还挺好记的。

第一个参数定义了感知到的亮度。它也是一个介于0%(即黑色)到100%(即白色)的百分数,也可以写成0到1.0的十进制形式,与HSL中的亮度定义非常类似,但LCHOKLCH在不同的色调表现中更加一致,更符合我们人眼的感知。

第二个参数色度值(chroma value)表示色彩的鲜艳程度。色度值为0则表示纯灰色,这与HSL中的饱和度也十分类似。从理论上讲,该参数值是没有范围限制的;但在实际应用中,OKLCH色度的取值往往不超过0.5(在sRGB色域中也不会超过0.33)。而在LCH中,色度的取值范围则是0到230。

最后一个参数是色调(hue)。它也是色相环上的某个角度值,类似HSL中的色调概念,只是具体数值重新做了调整。其取值范围为:从红色(red,30)依次过渡到黄色(yellow,90)、绿色(green,140)、青色(cyan,195)、蓝色(blue,260)、洋红色(magenta,330),最后又回到红色。

利用 color() 函数在更宽的色域中使用 RGB 颜色

CSS提供了一个color()函数,可以用来手动设置色域及颜色值。例如,color(display-p3 0.3 0.59 0.77)可以对P3色域下的红色、绿色、蓝色分别进行定义。该颜色值等效于oklch(64% 0.12 233deg)

个人认为在通常情况下,该颜色表示法不如前面介绍的几种实用,因为它采用的是一种基于RGB的范式(RGB-based paradigm),写起来也比较冗长。由于OKLABOKLCH等广色域表示法可以描述肉眼可见光谱中的任何颜色,因此,如若将来显示器升级到支持更广的色域标准,它们仍然可以胜任各种色彩的展示。

不过,color()函数除了支持sRGB、Display p3和Rec2020色域外,还支持更多冷僻色域,因此如果需要在特定色域内定义颜色,color()函数应该会非常有用。想了解更多color()函数的相关信息,可以参考MDN的在线文档:https://mng.bz/lMQ6。

总结一下,以上介绍的每种颜色表示法都是由以下参数分别定义的:

  • RGB—— 红、绿、蓝(值域均为0到255)
  • HSL—— 色调(角度值)、饱和度(百分数)、亮度(百分数)
  • HWB—— 色调(角度值)、白度(百分数)、黑度(百分数)
  • LAB—— 亮度(百分数),A轴(-125红色至125绿色),B轴(-125蓝色至125黄色)
  • OKLAB—— 亮度(百分数),A轴(-0.4红色至0.4绿色),B轴(-0.4蓝色至0.4黄色)
  • LCH—— 亮度(百分数)、色度(值域0到230)、色调(角度值)
  • OKLCH—— 亮度(百分数)、色度(值域0到0.5)、色调(角度值)

上述表示方法中,大部分还支持none关键字来代替其中的某个参数,用于表示该参数无关紧要。例如,oklch(100% 0 0deg)表示白色,因此色调的取值基本上没有意义。这时就可以写作oklch(100% 0 none)甚至是oklch(100% none none)

图 11.12 对比展示了几种典型颜色在指定的几种色彩空间中的不同表示方法。对于其中个别数值做了些微调。

以上这些特定的颜色也可以通过引用它们的合法名称来进行声明(如blue、lavender、lightgray等)。CSS中大约有150种类似的合法命名颜色(named colors)。有关命名颜色的完整列表,详见MDN官方文档<named-color>https://mng.bz/NRoN。

想要熟悉OKLCH或者其他任何色彩空间,最好的方法莫过于付诸实践。下一节我将深入介绍OKLCH在页面颜色配置中的具体用法,并推荐几个在使用过程中挺有帮助的实用工具。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号