初步概念
有几个概念需要澄清才能回答您的问题。
- 没有“正确匹配的对比色”之类的东西,而是一系列足够对比的颜色。例如,在海军蓝 (
#000080
) 背景上,您可以放置白色 ( #000000
) 文本(对比度 16.0),但它也适用于黄色(#ffff00
,对比度 14.9)、粉红色(#ffc0cb
,对比度 10.4)等。查看这些示例:
<p style="background:navy; color:white">white on navy</p>
<p style="background:navy; color:yellow">yellow on navy</p>
<p style="background:navy; color:pink">pink on navy</p>
您所指的算法与相对亮度和对比度的 WCAG 2.0 规范定义不匹配。你应该坚持后一种算法。其他人可能会提供有时有效有时无效的近似值(或者无论如何他们甚至可能提供错误的结果)。也就是说,WCAG 2.0 推荐的算法既不是特别难以实现,也不是计算密集型,因此不值得尝试寻找替代方案,甚至可能表现不佳。
WCAG 2.0 对比度算法解决了一个决策问题,即这两种颜色之间的对比度是否足够(让大多数用户能够相互区分)?但是,您似乎对解决(受约束的)优化问题更感兴趣,即(某些预设文本颜色中的哪一个)与该背景颜色的对比度最大?您应该记住,这是两个相关但不同的问题 - 不能忽视差异。我们稍后再讨论这个问题。
关于squizlabs HTML code sniffer,您说找不到相关代码。好吧,他们的 WCAG 2.0 对比度算法的实现可以很容易地在他们的 github repo 上搜索“对比度”找到:见contrastRatio
,relativeLum
和colourStrToRGB
函数。有趣的是,他们还提供了一种推荐算法,该算法提供了一种建议来改变前景或背景颜色(或两者),以遵守指定的对比度,同时将更改保持在最低限度。
问题方案
好的,也就是说,一旦我们更清楚问题的范围,让我们尝试回答问题:
问:我如何知道黑色或白色文本在对比度方面更适合特定背景?
答:一方面,您可以简单地计算背景颜色和黑色之间的颜色对比度;然后在你的背景颜色和白色之间;然后保留达到最佳对比度的那个。在伪js中:
function(yourColor) {
var black = "#000000";
var white = "#ffffff";
return contrastRatio(yourColor, black) > contrastRatio(yourColor, white) ? 'black' : 'white';
}
您可以使用 squizlabs 或您自己提供的对比度的实现(如果您遵循 WCAG 2.0 的描述,这并不难)。
请注意,在任何情况下,该contrastRatio
函数始终提供大于或等于 1.0 的值,因为它始终提供较亮颜色与较暗颜色的比率。因此,该函数是可交换的(您不需要注意参数的顺序)。
另请注意,squizlabsrecommendColour
功能对您没有用处,因为它们提供最接近推荐的颜色来匹配对比度规则,作为一般规则,它不需要是黑色或白色。
问:为什么有时这个或那个算法建议使用黑色(或白色)文本,尽管该颜色不符合对比度规则?
A:因为有时候,对于某些背景颜色和对比度级别,根本没有符合对比度规则的文字颜色。
你还记得优化和决策之间的区别吗?一件事是说“黑色是与您的背景颜色提供最大对比度的文本颜色”,另一件事是说“黑色文本与您的背景颜色提供大于 7 比 1 的对比度”。
有时,即使是可达到的最大对比度也不足以达到所需水平的对比度。这意味着您需要 (a) 选择不同的背景颜色,或 (b) 采用其他允许不太严格的对比度(即大文本)的样式,或 (c) 在您的级别上拒绝遵守 WCAG 2.0选择了。
让我们用几个例子来说明:
+-----------+------------+------------- --+---------+--------+
| 案例 | 目标 C | 文字流 | 白色的?| 黑色的?|
+-----------+------------+------------- --+---------+--------+
| AA大号| 3:1 | 0.000 - 0.100 | 好的 | 否 |
| AA大号| 3:1 | 0.100 - 0.300 | 好的 | 好的 |
| AA大号| 3:1 | 0.300 - 1.000 | 否 | 好的 |
| AA小,AAA大| 4.5:1 | 0.000 - 0.175 | 好的 | 否 |
| AA小,AAA大| 4.5:1 | 0.175 - 0.183 | 好的 | 好的 |
| AA小,AAA大| 4.5:1 | 0.183 - 1.000 | 否 | 好的 |
| AAA小文| 7:1 | 0.000 - 0.100 | 好的 | 否 |
| AAA小文| 7:1 | 0.100 - 0.300 | 否 | 否 |
| AAA小文| 7:1 | 0.300 - 1.000 | 好的 | 好的 |
+-----------+------------+------------- --+---------+--------+
正如您可能注意到的,有一系列颜色,其亮度在 0.1 和 0.3 之间,黑色和白色的对比度在 3:1 和 7:1之间。这意味着这些背景颜色与黑色和白色都具有足够的对比度,可以将它们用于大的白色或大的黑色文本,并符合 WCAG SC 1.4.3(AA 级)(尽管它们中只有一种是最佳选择)案例:白色表示背景亮度介于 0.100 和 0.179 之间,黑色表示介于 0.179 和 0.300 之间)。但是,另一方面,这些相同的颜色没有足够的对比度用于任何小文本,无论其颜色如何,同时仍符合 WCAG SC 1.4.6(AAA 级)。最后,关于小文本和 WCAG SC 1.4.3(AA 级),总是有一种颜色(黑色或白色)可以提供足够的对比度(甚至两者都适用的范围很小)。
带回家的消息
- 使用 WCAG 2.0 颜色对比算法的适当实现(squizlabs 可能是一个合适的选择)。
- 在您的代码中,将背景颜色的对比度值与白色和黑色进行比较,然后选择提供最大对比度的文本颜色。
- 如果您的目标是 WCAG AA,则保证您将始终获得符合 SC 1.4.3 的文本颜色。但是,请注意,如果您想遵守 WCAG AAA,可能有一些背景颜色根本无法用于较小的文本(无论是黑色还是白色),而不会通过 SC 1.4.6。
结尾
您所指的 optional.is 的初始算法受到WCAG 1.0 的信息草案建议的启发。但是,请注意这是非官方的(因为它从未从草案状态升级),已过时(因为它早已被 WCAG 2.0 取代),并且实现可能不正确(因为整个算法需要考虑两个变量:亮度差异和色差,而您所指的实现仅考虑前者)。
我已经包含了一个无法访问的表,这是由于 SO markdown 限制,它不允许任意 HTML,为此道歉;无论如何,我认为没有必要理解答案。