不靠猜也能达到 WCAG 的颜色对比度要求
对普通正文,WCAG 的 AA 级要求文字与背景的对比度至少为 4.5:1。大号文字需要 3:1。界面组件和有实际含义的图形需要 3:1。AAA 级把正文提高到 7:1,大号文字提高到 4.5:1。比值的范围是从 1:1(两种颜色完全相同)到 21:1(纯黑配纯白)。
这件事没法靠肉眼判断。在你的显示器上看起来可读性差不多的两组配色,可能分别落在阈值的两侧,所以比值必须计算出来。
各项阈值
| 对象 | AA | AAA |
|---|---|---|
| 普通文字 | 4.5:1 | 7:1 |
| 大号文字 | 3:1 | 4.5:1 |
| 界面组件与图形对象 | 3:1 | 没有更高的门槛 |
这些来自三条成功准则:AA 级的 1.4.3 对比度(最低),AAA 级的 1.4.6 对比度(增强),以及 AA 级的 1.4.11 非文本对比度,最后这条覆盖控件的视觉边界,以及图形中你必须看清才能理解其含义的那些部分。
大号文字指至少 18 磅,或者加粗时至少 14 磅,换算下来大约是 24px 常规字重或约 18.5px 加粗。它不等于“标题”:就规则而言,一个 20px 的标题属于普通文字,需要完整的 4.5:1。
有几类内容可以豁免:纯装饰性文字、处于非激活状态的控件中的文字、作为一幅还包含其他重要视觉内容的图片一部分的文字,以及标识字样。占位文字和辅助说明文字不在豁免之列。
这个比值实际测量的是什么
公式比较的是两种颜色的相对亮度:
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
相对亮度是一个从 0(黑)到 1(白)的数字,表示一种颜色发出多少光。它的算法是先对每个通道撤销 sRGB 的伽马曲线,然后做加权:
L = 0.2126 R + 0.7152 G + 0.0722 B (on linearised channels)
两边都加上的 0.05 模拟了少量从屏幕上反射回来的环境光,这也是为什么最大值是 21 而不是无穷大。
由此可以得出两点。比值只取决于亮度,与色相无关,所以两种色相相差极大的颜色放在一起仍然可能几乎彼此不可见。另外它是对称的,所以你把哪一种颜色叫作前景并不重要。
相对亮度不是明亮程度
看看那几个权重。绿色贡献了约 72% 的亮度,红色约 21%,蓝色勉强 7%。这是一个人类视觉的模型,不是“一种颜色看起来有多鲜艳”的模型,它给出的结果在你习惯之前会觉得别扭。
- 纯黄色
#FFFF00配白色约为 1.07:1,几乎不可见,尽管黄色给人的感觉是很强烈的颜色。 - 同样的黄色配黑色约为 19.6:1,几乎和白配黑一样高。
- 纯蓝色
#0000FF配黑色约为 2.4:1,所有标准都不达标,尽管它看起来醒目而饱和。
这也是为什么 HSL 的亮度是一个糟糕的替代指标。两种颜色在 HSL 里都可以处在 50% 的亮度,而相对亮度却相差很大,因为 HSL 把色相和亮度当成互相独立的,而视觉并不是这样。请先转换,再测量,而不是假定亮度上迈出一步就等于对比度上迈出一步。
反复出现的错误
白底上的灰色正文。 这是最大的一个。在白底上还能通过 AA 的最浅的灰是 #767676 左右,算出来是 4.54:1。再浅一档的 #777777 是 4.48:1,不达标。像 #999999 这类流行的“淡化”灰落在 2.9:1 附近,不到要求的三分之二。如果你想在白底上达到 AAA,大约需要 #595959,它正好是 7:1。
占位文字和辅助说明文字。 因为它们是次要信息,往往被设置得比正文浅好几档。它们仍然是文字,仍然需要 4.5:1。
半透明颜色。 如果元素的不透明度是 60%,那么按声明的颜色算出来的比值毫无意义。要先算出屏幕上实际呈现的合成颜色,再去测量它。
图片、渐变和视频之上的文字。 比值逐像素变化,而最糟的那个像素才是关键。通常的解决办法是在文字后面加一层遮罩,而不是指望照片一直都是暗的。
用品牌色做的按钮。 中等明度品牌色配白字,非常经常地落在 3:1 到 4.5:1 之间,作为图形对象算通过,作为文字标签算不达标。要么把按钮调暗,要么明知它不达标而接受它。
焦点指示器和纯图标按钮。 两者都适用 3:1 的非文本规则。用同一种颜色稍微不同的一档来做焦点环是常见的疏漏,一个作为按钮全部内容的灰色图标也是。
靠反转做出来的深色模式。 把浅色配色方案翻过来并不能保住比值,因为亮度并不是围绕中点对称的。纯白配纯黑给出最大的 21:1,但很多人觉得那种光晕不舒服,所以用近白色配非常深的灰,比如 #E6E6E6 配 #121212 约为 15:1,是常见的折中。
从截图上取样测量。 用吸管工具去点抗锯齿文字的边缘,取到的是文字和背景的混合色,不是文字的颜色。要取笔画粗壮处的中间,或者更好的办法是直接从你的 CSS 里读数值。
一套不用猜的工作流程
先把背景定下来,然后把前景调深或调浅,直到它越过阈值并留出一点余量,再把这一对颜色记录下来。用通过审核的颜色对来构建配色方案,而不是用通过审核的单个颜色:一种颜色本身谈不上是否无障碍,只有在组合中才有意义。所有状态都要检查,不只是静止状态,如果你还提供深色模式,两套主题都要查。
最后一点说明。一个更新的感知模型 APCA 正在为 WCAG 的未来版本开发中,它的行为相当不同,尤其是在深色背景配浅色文字的情况下。了解一下是有价值的,但今天要遵循的数字仍然是上面这些 WCAG 2 的比值。