3

我正在尝试为给定的背景颜色找到正确的匹配对比色,它将通过 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';   }

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

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

我可以使用 JS 中的另一种算法/函数来返回有效的对比色来通过这些准则吗?

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

4

3 回答 3

7

初步概念

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

  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>

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

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

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

问题方案

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

问:我如何知道黑色或白色文本在对比度方面更适合特定背景?

答:一方面,您可以简单地计算背景颜色和黑色之间的颜色对比度;然后在你的背景颜色和白色之间;然后保留达到最佳对比度的那个。在伪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 级),总是有一种颜色(黑色或白色)可以提供足够的对比度(甚至两者都适用的范围很小)。

带回家的消息

  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,为此道歉;无论如何,我认为没有必要理解答案。

于 2015-04-04T17:45:58.427 回答
1

您的算法与官方 WCAG 公式不匹配。

您可以在以下页面上查看获得对比度的 WCAG 公式: http ://www.w3.org/TR/WCAG20-TECHS/G17.html ,这要复杂得多。

我不知道他们在哪里找到这个...

于 2015-03-06T07:31:56.537 回答
0

w3.org上的“更复杂”的表格用于从sRGB色彩空间转换为标准RGB

的公式RGB很简单。

  1. 对于每种颜色,找到它的“相对亮度”

    L = 0.2126 * R + 0.7152 * G + 0.0722 * B
    
  2. 计算比率:

    (higherRelBrightness + 0.05) / (lowerRelBrightness + 0.05)
    

    这将从 1.0(相同亮度)到 21.0(#000 到 #fff)

于 2021-09-21T08:16:46.373 回答