调整给定的颜色对以符合 ePub 的 W3C 无障碍标准

Adapt given color pairs to adhere to W3C Accessibility standard for ePubs

我们正努力制作符合 W3C 辅助功能标准的 ePub 出版物。剩下的问题之一是文本颜色和背景颜色之间的颜色对比度不足。我们使用 Ace by DAISY(很棒的工具!),它以文本形式和 JSON:

提供有关此类问题的信息

这里是 JSON(从 dct:description 中提取两个颜色值不是很简单,但我们管理了一个正则表达式):

{
  "@type": "earl:assertion",
  "earl:result": {
    "earl:outcome": "fail",
    "dct:description": "Element has insufficient color contrast of 2.86 (foreground color: #fd5f07, background color: #fff5ea, font size: 28.1pt (37.52px), font weight: normal). Expected contrast ratio of 3:1",
    "earl:pointer": {
      "cfi": [
        "/4/2/6/2",
        "/4/2/6"
      ],
      "css": [
        ".inbrief-title",
        ".inbrief"
      ]
    },
    "html": "<div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"inbrief-title\">In Brief</div> <!--##--> <div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"box-container inbrief\">"
  },
  "earl:assertedBy": "aXe",
  "earl:mode": "automatic",
  "earl:test": {
    "earl:impact": "serious",
    "dct:title": "color-contrast",
    "dct:description": "Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds",
    "help": {
      "url": "http://kb.daisy.org/publishing/docs/css/color.html",
      "dct:title": "Color",
      "dct:description": "Elements must have sufficient color contrast"
    },
    "rulesetTags": [
      "cat.color",
      "wcag2aa",
      "wcag143"
    ]
  }
},

但是,我想以编程方式调整这些颜色,以通过尽可能少地更改颜色来在背景颜色和文本颜色之间创建足够的对比度。例如,如果有浅黄色和白色文字,则将黄色更改为较深的色调,直到满足对比度要求。或者,相反,将文本设为黑色。

有没有一种可以实现的算法可以做到这一点?我找不到任何有用的东西。在描述上面的用例时,我发现自己注意到这可能是一个相当主观的决定,因此很难自动化。

您要做的第一件事是决定要更改哪种颜色,前景还是背景。我可能会做的是决定哪种颜色是白色或黑色最远,因为它的值可以改变最多。

不过在这之前,你得弄清楚哪个颜色是浅色,哪个颜色是深色。幸运的是,这很容易。由于白色为#fff,黑色为#000,所以颜色值越小(即越接近#000)的颜色越深

然后只需从#fff 中减去浅色(十六进制减法或将颜色转换为十进制)并将其与深色进行比较。

如果浅色减去的值小于深色,则浅色更接近白色,而深色更接近黑色,因此您需要开始修改较深的颜色。

如果浅色减去的值大于深色,则浅色与白色的距离比深色与黑色的距离远,因此您需要开始修改浅色。

改变颜色时,只需将每个RGB分量加1或减1即可。如果您使浅色变浅,则加 1;如果您使深色变深,则减 1。

从每个 RGB 中加减 1 后,计算亮度对比度以查看是否高于 4.5(如果字体较小)或高于 3(如果字体较大 - 其中“大”是定义为 14pt 粗体或 18pt 正常)。

contrast ratio formula 有点乱但是可行。

(L1 + 0.05) / (L2 + 0.05)

L1 is the relative luminance of the lighter of the colors, and
L2 is the relative luminance of the darker of the colors.

您已经知道哪种颜色较浅,哪种颜色较深。

relative luminance值(L)是乱七八糟的部分,虽然它最初看起来很简单。只是:

L = 0.2126 * R + 0.7152 * G + 0.0722 * B

基本上,它是 21% 的红色、71% 的蓝色、7% 的绿色。但这不是颜色中 R、G 和 B 的直接值。首先,您必须取每个 R、G、B 值并除以 255。然后根据该值,您可以对这些值进行一些处理。

R = R / 255
if R <= 0.03928 then R = R/12.92
else R = ((R+0.055)/1.055) ^ 2.4 

对 G 和 B 也这样做。现在你有了新的 R、G 和 B 值,然后 你可以应用上面的 21%/71%/7% 相对亮度,这会给你 L1 或 L2,然后您可以将 0.05 添加到两个值并将 L1 除以 L2。

我告诉过你这很乱但可行。这将为您提供应该在 1 到 21 之间的对比度值。(1 是当两种颜色相同时 [白色对白色,红色对红色,橙色对橙色等],21 是当两种颜色为黑色时( #000) 和白色 (#fff)。

如果您还没有达到 4.5(或 3.0,取决于字体大小),则再次从每个 R/G/B 中加或减 1 并再次计算比率。

为了好玩,这里有一个例子:

color1 = #5EBA7D(Whosebug 上显示赞成票值的绿色背景色)

color2 = #FDF7E2(侧边栏在 Whosebug 上的黄色背景色)

(upvote 文本颜色是白色,但对于示例来说很无聊,所以我选择了黄色)。

前景或背景颜色无关紧要。你得到相同的比率。所以让我们使用 C1 作为前景,C2 作为背景。如果使用工具,例如 CCA, it shows a value of 2.2:1, which fails WCAG 1.4.3.

让我们将这些数字代入公式。

C1

#5EBA7D
R = #5E (94)
G = #BA (186)
B = #7D (125)

每一个除以 255

R = 94/255  = 0.368
G = 186/255 = 0.729
B = 125/255 = 0.490

None 这些值小于 0.03928,所以我们必须应用混乱的部分。加上 0.055,然后除以 1.055,然后将其提高到 2.4 的次方。

R = ((0.368 + 0.055)/1.055) ^ 2.4 = 0.112
G = ((0.729 + 0.055)/1.055) ^ 2.4 = 0.491
B = ((0.490 + 0.055)/1.055) ^ 2.4 = 0.205

现在您应用百分比 (21%/71%/7%) 以获得第一种颜色的亮度值。

L1 = 0.2126 * R + 0.7152 * G + 0.0722 * B
L1 = 0.2126 * (.112) + 0.7152 * (.491) + 0.0722 * (.205)
L1 = 0.024 + 0.351 + 0.015
L1 = 0.390

然后你对另一种颜色做这个得到L2 = 0.929

L2 是黄色,所以实际上是较浅的颜色,在原始公式中应该是 L1。所以我们将颜色更深的绿色设为 L2。

(L1 + 0.05) / (L2 + 0.05)
= (0.929 + 0.05) / (0.390 + 0.05)
= 2.226

如果您使用颜色对比工具,您应该得到相同的值,尽管大多数工具通常四舍五入到小数点后一位,因此您将得到 2.2。

既然你知道了比例,那么哪种颜色离黑色或白色更远,你就知道要调整哪种颜色了吗?

color1 = #5EBA7D (green)
color2 = #FDF7E2 (yellow)

较小的数字更暗(接近 #000 黑色),因此应该是 #5EBA7D(绿色)。

浅色(#FDF7E2,黄色)与白色(#fff)相差多少?

#FFFFFF - #FDF7E2 = #02081D

现在,哪个更大?深色,#5EBA7D(绿色),或者从黄色到白色的距离,#02081D?在这种情况下,绿色更大,因此它与黑色的距离比黄色与白色的距离更远。

进行直觉检查,这是有道理的。绿色不是很深,有点浅绿色,所以它不是很接近黑色。但是黄色很淡,接近白色

由于绿色与黑色的距离远大于黄色与白色的距离,因此您可以开始调整绿色并使其更暗。为此,请从每个 R/G/B 值中减去 1,然后重新计算亮度。它可能不会有太大变化,因此您必须不断调整绿色并使其变暗,直到达到 4.5(或 3.0,取决于字体大小)。

如果您对这种情况进行编程,绿色最终应该达到 #258144(最终从每个 RGB 值中减去 57),其与黄色的颜色比为 4.6。

如果在达到合适的对比度之前任何 RGB 值达到 0,则必须开始通过将每个 RGB 值加 1 并重新计算对比度来使光的颜色更亮。通过从每个 RGB 中加或减 1,可以保持色调。绿色还是绿色但是更深了,或者黄色还是黄色但是更淡了。

你希望你现在没有问这个问题吗?

次要更新: 每次将 RGB 值调整 1 并重新计算亮度可能不是很有效。在我的示例中,必须执行 57 次。您可能希望从每个 RGB 分量而不是 1 添加或减去 10,看看您得到的值与 4.5 的接近程度。如果还没有,再次调整 10。一旦你大于 4.5,你可以稍微调整它并在相反的方向调整 2,直到你接近 4.5 而不会下降。