为给定的十六进制背景值找到正确的 WCAG AA 对比色

Tim*_*Tim 3 javascript wcag2.0

我正在尝试为给定的背景颜色找到正确的匹配对比色,该颜色将通过 WCAG AA 指南(文本小于 14 像素)。

我看到的算法是..

  function getContrastYIQ(hexcolor){

    var r = parseInt(hexcolor.substr(1,2),16);
    var g = parseInt(hexcolor.substr(3,2),16);
    var b = parseInt(hexcolor.substr(5,2),16);
    var yiq = ((r*299)+(g*587)+(b*114))/1000;

    return (yiq >= 128) ? 'dark-color' : 'light-color';   }
Run Code Online (Sandbox Code Playgroud)

参考:http : //optional.is/required/2011/01/12/maximum-color-contrast/

但是,对于这些颜色,某些颜色(如 #e8540a 和 #ff4249)在未通过颜色对比度准则时返回浅色。

我可以使用 JS 中的另一个算法/函数返回一个有效的对比色,而不是通过这些指南?

http://squizlabs.github.io/HTML_CodeSniffer/似乎有正确的算法......但似乎无法找到相关代码来转换为 JS。有人有什么建议吗?

ysm*_*tin 6

初步概念

有几个概念需要澄清才能回答您的问题。

  1. 没有“正确匹配的对比色”这样的东西,而是一系列足够对比的颜色。例如,在海军蓝 ( #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>
Run Code Online (Sandbox Code Playgroud)

  1. 您引用的算法与 WCAG 2.0相对亮度对比度的规范定义不匹配。您应该坚持使用后一种算法。其他人可能会提供有时有效有时无效的近似值(或者无论如何他们甚至可能提供错误的结果)。也就是说,WCAG 2.0 推荐的算法既不是特别难实现,也不是计算密集型,因此不值得尝试寻找替代方案,甚至可能表现不佳。

  2. WCAG 2.0 对比度算法解决了一个决策问题,即这两种颜色之间的对比度是否足够(对于大多数用户来说相互区分)?但是,您似乎对解决(受约束的)优化问题更感兴趣,即哪种(某些预设文本颜色)与此背景颜色的对比度最大?您应该记住,这是两个相关但不同的问题 - 不能忽视差异。我们稍后会回到这个话题。

  3. 关于squizlabs HTML 代码嗅探器,您表示找不到相关代码。好吧,他们对 WCAG 2.0 对比度算法的实现可以很容易地找到,在他们的 github 存储库上搜索“对比度”:参见contrastRatio,relativeLumcolourStrToRGB函数。有趣的是,他们还提供了一种推荐算法,该算法提供了改变前景或背景颜色(或两者)的建议,以遵守指定的对比度,同时将更改保持在最低限度。

问题方案

好的,也就是说,一旦我们更清楚问题的范围,让我们尝试回答问题:

问:就对比度而言,我如何知道黑色或白色文本更适合特定背景?

答:一方面,您可以简单地计算背景颜色和黑色之间的颜色对比度;然后在你的背景颜色和白色之间;然后保留达到最佳对比度的那个。在伪js中:

function(yourColor) {
  var black = "#000000";
  var white = "#ffffff";
  return contrastRatio(yourColor, black) > contrastRatio(yourColor, white) ? 'black' : 'white';
}
Run Code Online (Sandbox Code Playgroud)

您可以使用 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 级),总有一种颜色(黑色或白色)可以提供足够的对比度供使用(甚至有一个小范围都适用)。

带回家的消息

  1. 使用 WCAG 2.0 颜色对比度算法的适当实现(squizlabs 可能是合适的选择)。
  2. 在您的代码中,将背景颜色与白色和黑色的对比度值进行比较,然后选择提供最大对比度的文本颜色。
  3. 如果您的目标是 WCAG AA,则保证您将始终获得符合 SC 1.4.3 的文本颜色。但是,请注意,如果您想遵守 WCAG AAA,则可能有一些背景颜色根本无法与较小的文本(无论是黑色还是白色)一起使用,而不会使 SC 1.4.6 失败。

结尾

您所指的 optional.is 的初始算法的灵感来自WCAG 1.0信息性草案建议。但是,请注意这是非官方的(因为它从未从草案状态中进步),已经过时(因为它早已被 WCAG 2.0 取代),并且实现可能是不正确的(因为整个算法需要考虑两个变量:亮度差异和色差,而您所指的实现只考虑前者)。

我包含了一个无法访问的表格,这是由于 SO Markdown 限制,不允许任意 HTML,为此道歉;无论如何我认为没有必要了解答案。