使用 Shell 脚本让网站更易读

计算您网站文本和背景之间的对比度,以确保您的网站易于阅读。
132 位读者喜欢这篇文章。
Team communication, chat

如果您希望人们觉得您的网站有用,他们需要能够阅读它。您为文本选择的颜色会影响您网站的可读性。不幸的是,网页设计中一种流行的趋势是在打印文本时使用低对比度颜色,例如白色背景上的灰色文本。也许这在网页设计师看来非常酷,但对于我们许多人来说,这真的很难阅读。

W3C 提供了 Web 内容可访问性指南,其中包括帮助网页设计师选择文本和背景颜色的指导,这些颜色可以很容易地区分。这被称为“对比度”。W3C 对比度比率的定义需要进行多次计算:给定两种颜色,您首先计算每种颜色的相对亮度,然后计算对比度比率。该比率将在 1 到 21 之间(通常写为 1:1 到 21:1)。对比度比率越高,文本在背景中就越突出。例如,白色背景上的黑色文本非常醒目,对比度比率为 21:1。而白色背景上的白色文本是不可读的,对比度比率为 1:1。

W3C 表示正文文本的对比度比率应至少为 4.5:1,标题至少为 3:1。但这似乎是最低限度。W3C 还建议正文文本至少为 7:1,标题至少为 4.5:1。

计算对比度比率可能很繁琐,因此最好将其自动化。我使用这个方便的 Bash 脚本完成了这项工作。一般来说,该脚本执行以下操作

  1. 获取文本颜色和背景颜色
  2. 计算每种颜色的相对亮度
  3. 计算对比度比率

获取颜色

您可能知道显示器上的每种颜色都可以用红色、绿色和蓝色 (R, G, 和 B) 表示。为了计算颜色的相对亮度,我的脚本需要知道颜色的红色、绿色和蓝色分量。理想情况下,我的脚本会以单独的 R、G 和 B 值读取此信息。网页设计师可能知道他们喜欢的颜色的特定 RGB 代码,但大多数人不知道不同颜色的 RGB 值。相反,大多数人通过诸如“红色”或“金色”或“栗色”之类的名称来引用颜色。

幸运的是,GNOME Zenity 工具有一个颜色选择器应用程序,可让您使用不同的方法选择颜色,然后以“rgb(R,G,B)”的预测格式返回 RGB 值。使用 Zenity 可以轻松获取颜色值

color=$( zenity --title 'Set text color' --color-selection --color='black' )

以防用户(意外地)单击“取消”按钮,脚本会假定一种颜色

if [ $? -ne 0 ] ; then
	echo '** color canceled .. assume black'
	color='rgb(0,0,0)'
fi

我的脚本执行类似的操作来将背景颜色值设置为 $background

计算相对亮度

一旦您有了前景色 $color 和背景色 $background,下一步是计算每种颜色的相对亮度。在其网站上,W3C 提供了计算相对亮度的算法

对于 sRGB 色彩空间,颜色的相对亮度定义为

L = 0.2126 * R + 0.7152 * G + 0.0722 * B 其中 R、G 和 B 定义为

如果 RsRGB <= 0.03928 则 R = RsRGB/12.92

否则 R = ((RsRGB+0.055)/1.055) ^ 2.4

如果 GsRGB <= 0.03928 则 G = GsRGB/12.92

否则 G = ((GsRGB+0.055)/1.055) ^ 2.4

如果 BsRGB <= 0.03928 则 B = BsRGB/12.92

否则 B = ((BsRGB+0.055)/1.055) ^ 2.4

并且 RsRGB、GsRGB 和 BsRGB 定义为

RsRGB = R8bit/255

GsRGB = G8bit/255

BsRGB = B8bit/255

由于 Zenity 以“rgb(R,G,B)”格式返回颜色值,因此脚本可以轻松地分解 R、B 和 G 值以计算相对亮度。AWK 使这项任务变得简单,使用逗号作为字段分隔符 (-F,) 并使用 AWK 的 substr() 字符串函数从“rgb(R,G,B)”颜色值中选择我们想要的文本

R=$( echo $color | awk -F, '{print substr($1,5)}' )
G=$( echo $color | awk -F, '{print $2}' )
B=$( echo $color | awk -F, '{n=length($3); print substr($3,1,n-1)}' )

(有关使用 AWK 提取和显示数据的更多信息,请获取我们的 AWK 速查表。)

计算最终相对亮度最好使用 BC 计算器完成。BC 支持计算中需要的简单if-then-else,这使得这部分很简单。但是由于 BC 无法直接计算使用非整数指数的指数运算,我们需要使用自然对数进行一些额外的数学运算

echo "scale=4
rsrgb=$R/255
gsrgb=$G/255
bsrgb=$B/255
if ( rsrgb <= 0.03928 ) r = rsrgb/12.92 else r = e( 2.4 * l((rsrgb+0.055)/1.055) )
if ( gsrgb <= 0.03928 ) g = gsrgb/12.92 else g = e( 2.4 * l((gsrgb+0.055)/1.055) )
if ( bsrgb <= 0.03928 ) b = bsrgb/12.92 else b = e( 2.4 * l((bsrgb+0.055)/1.055) )
0.2126 * r + 0.7152 * g + 0.0722 * b" | bc -l

这会将多条指令传递给 BC,包括作为相对亮度公式一部分的 if-then-else 语句。然后 BC 打印最终值。

计算对比度比率

有了文本颜色和背景颜色的相对亮度,现在脚本可以计算对比度比率了。W3C 使用以下公式确定对比度比率

(L1 + 0.05) / (L2 + 0.05),其中

L1 是颜色中较浅颜色的相对亮度,以及

L2 是颜色中较深颜色的相对亮度

给定两个相对亮度值 $r1$r2,使用 BC 计算器很容易计算对比度比率

echo "scale=2
if ( $r1 > $r2 ) { l1=$r1; l2=$r2 } else { l1=$r2; l2=$r1 }
(l1 + 0.05) / (l2 + 0.05)" | bc

这使用 if-then-else 语句来确定哪个值($r1$r2)是较浅或较深的颜色。BC 执行生成的计算并打印结果,脚本可以将其存储在一个变量中。

最终脚本

有了以上内容,我们可以将所有内容整合到一个最终脚本中。我使用 Zenity 在文本框中显示最终结果

#!/bin/sh
# script to calculate contrast ratio of colors

# read color and background color:
# zenity returns values like 'rgb(255,140,0)' and 'rgb(255,255,255)'

color=$( zenity --title 'Set text color' --color-selection --color='black' )
if [ $? -ne 0 ] ; then
	echo '** color canceled .. assume black'
	color='rgb(0,0,0)'
fi

background=$( zenity --title 'Set background color' --color-selection --color='white' )
if [ $? -ne 0 ] ; then
	echo '** background canceled .. assume white'
	background='rgb(255,255,255)'
fi

# compute relative luminance:

function luminance()
{
	R=$( echo $1 | awk -F, '{print substr($1,5)}' )
	G=$( echo $1 | awk -F, '{print $2}' )
	B=$( echo $1 | awk -F, '{n=length($3); print substr($3,1,n-1)}' )

	echo "scale=4
rsrgb=$R/255
gsrgb=$G/255
bsrgb=$B/255
if ( rsrgb <= 0.03928 ) r = rsrgb/12.92 else r = e( 2.4 * l((rsrgb+0.055)/1.055) )
if ( gsrgb <= 0.03928 ) g = gsrgb/12.92 else g = e( 2.4 * l((gsrgb+0.055)/1.055) )
if ( bsrgb <= 0.03928 ) b = bsrgb/12.92 else b = e( 2.4 * l((bsrgb+0.055)/1.055) )
0.2126 * r + 0.7152 * g + 0.0722 * b" | bc -l
}

lum1=$( luminance $color )
lum2=$( luminance $background )

# compute contrast

function contrast()
{
	echo "scale=2
if ( $1 > $2 ) { l1=$1; l2=$2 } else { l1=$2; l2=$1 }
(l1 + 0.05) / (l2 + 0.05)" | bc
}

rel=$( contrast $lum1 $lum2 )

# print results

( cat<<EOF
Color is $color on $background

Contrast ratio is $rel
Contrast ratios can range from 1 to 21 (commonly written 1:1 to 21:1).

EOF

if [ ${rel%.*} -ge 4 ] ; then
	echo "Ok for body text"
else
	echo "Not good for body text"
fi
if [ ${rel%.*} -ge 3 ] ; then
	echo "Ok for title text"
else
	echo "Not good for title text"
fi

cat<<EOF

The W3C says this:

1.4.3 Contrast (Minimum): The visual presentation of text and images of text has a contrast ratio of at least 4.5:1, except for the following: (Level AA)

    Large Text: Large-scale text and images of large-scale text have a contrast ratio of at least 3:1;

    Incidental: Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement.

    Logotypes: Text that is part of a logo or brand name has no minimum contrast requirement.

and:

1.4.6 Contrast (Enhanced): The visual presentation of text and images of text has a contrast ratio of at least 7:1, except for the following: (Level AAA)

    Large Text: Large-scale text and images of large-scale text have a contrast ratio of at least 4.5:1;

    Incidental: Text or images of text that are part of an inactive user interface component, that are pure decoration, that are not visible to anyone, or that are part of a picture that contains significant other visual content, have no contrast requirement.

    Logotypes: Text that is part of a logo or brand name has no minimum contrast requirement.
EOF
) | zenity --text-info --title='Relative Luminance' --width=800 --height=600

最后,我喜欢包含有关 W3C 建议的参考信息,以提醒自己。

Zenity 颜色选择器完成了所有解释颜色的繁重工作,用户可以通过单击色轮或输入值来选择颜色。Zenity 接受网站上使用的标准十六进制颜色值,例如 #000000 或 #000 或 rgb(0,0,0)(所有这些都是黑色)。这是一个白色背景上的黑色文本的示例计算

Picking black in Zenity

Picking white in Zenity

Calculating contrast ratio of black and white

Zenity 还理解标准颜色名称,如 cadetblue 或 orange 或 gold。在 Zenity 中输入颜色名称,然后按 Tab 键,Zenity 会将颜色名称转换为十六进制颜色值,如黑色文本在金色背景上的示例计算中所示

Selecting white by name in Zenity

opensource.com

White's hex value in Zenity

Selecting gold by name in Zenity

Gold's hex value in Zenity

Calculating contrast ratio of white and gold

 

标签
photo of Jim Hall
Jim Hall 是一位开源软件倡导者和开发人员,以 GNOME 的可用性测试以及 FreeDOS 的创始人兼项目协调员而闻名。

4 条评论

如果说有什么需要注意的地方,那就是还需要考虑各种显示屏幕、它们的亮度设置和环境照明。我认为您需要一些经验性的工作来用自己的眼睛测试一下。

为了使脚本对我有效,我必须删除函数声明“luminance”和“contrast”中的括号。

我希望更多的网页设计师会阅读这篇文章。我不是程序员(正在尝试学习 C++ 和 Python),但我无法告诉您,访问一个网站,并且他们的文本如此难以辨认,以至于我不得不复制它并将其粘贴到文本编辑器 (gEdit) 中才能阅读,这有多令人沮丧!有时试图成为一个“看起来很酷”的网站?……可能会让您失去访问者和点击量,因为现在?……无论我多么想阅读网站上的某些内容?……如果它难以阅读?……我只是关闭它,然后在其他地方查找我正在寻找的信息!很棒的文章!!

非常有趣和有用

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.