利用Shell腳本讓網(wǎng)站更具可讀性
如果希望人們發(fā)現(xiàn)你的網(wǎng)站實(shí)用,那么他們需要能夠閱讀它。為文本選擇的顏色可能會(huì)影響網(wǎng)站的可讀性。不幸的是,網(wǎng)頁(yè)設(shè)計(jì)中的一種流行趨勢(shì)是在打印輸出文本時(shí)使用低對(duì)比度的顏色,就像在白色背景上的灰色文本。對(duì)于 Web 設(shè)計(jì)師來(lái)說(shuō),這也許看起來(lái)很酷,但對(duì)于許多閱讀它的人來(lái)說(shuō)確實(shí)很困難。
W3C 提供了《Web 內(nèi)容可訪問(wèn)性指南Web Content Accessibility Guidelines》,其中包括幫助 Web 設(shè)計(jì)人員選擇易于區(qū)分文本和背景色的指導(dǎo)。z這就是所謂的“對(duì)比度contrast ratio”。 W3C 定義的對(duì)比度需要進(jìn)行一些計(jì)算:給定兩種顏色,首先計(jì)算每種顏色的相對(duì)亮度,然后計(jì)算對(duì)比度。對(duì)比度在 1 到 21 的范圍內(nèi)(通常寫(xiě)為 1:1 到 21:1)。對(duì)比度越高,文本在背景下的突出程度就越高。例如,白色背景上的黑色文本非常醒目,對(duì)比度為 21:1。對(duì)比度為 1:1 的白色背景上的白色文本不可讀。
W3C 說(shuō),正文 的對(duì)比度至少應(yīng)為 4.5:1,標(biāo)題至少應(yīng)為 3:1。但這似乎是最低限度的要求。W3C 還建議正文至少 7:1,標(biāo)題至少 4.5:1。
計(jì)算對(duì)比度可能比較麻煩,因此最好將其自動(dòng)化。我已經(jīng)用這個(gè)方便的 Bash 腳本做到了這一點(diǎn)。通常,腳本執(zhí)行以下操作:
- 獲取文本顏色和背景顏色
 - 計(jì)算相對(duì)亮度
 - 計(jì)算對(duì)比度
 
獲取顏色
你可能知道顯示器上的每種顏色都可以用紅色、綠色和藍(lán)色(R、G 和 B)來(lái)表示。要計(jì)算顏色的相對(duì)亮度,腳本需要知道顏色的紅、綠和藍(lán)的各個(gè)分量。理想情況下,腳本會(huì)將這些信息讀取為單獨(dú)的 R、G 和 B 值。 Web 設(shè)計(jì)人員可能知道他們喜歡的顏色的特定 RGB 代碼,但是大多數(shù)人不知道不同顏色的 RGB 值。作為一種替代的方法是,大多數(shù)人通過(guò) “red” 或 “gold” 或 “maroon” 之類的名稱來(lái)引用顏色。
幸運(yùn)的是,GNOME 的 Zenity 工具有一個(gè)顏色選擇器應(yīng)用程序,可讓你使用不同的方法選擇顏色,然后用可預(yù)測(cè)的格式 rgb(R,G,B) 返回 RGB 值。使用 Zenity 可以輕松獲得顏色值:
- color=$( zenity --title 'Set text color' --color-selection --color='black' )
 
如果用戶(意外地)單擊 “Cancel(取消)” 按鈕,腳本將假定一種顏色:
- if [ $? -ne 0 ] ; then
 - echo '** color canceled .. assume black'
 - color='rgb(0,0,0)'
 - fi
 
腳本對(duì)背景顏色值也執(zhí)行了類似的操作,將其設(shè)置為 $background。
計(jì)算相對(duì)亮度
一旦你在 $color 中設(shè)置了前景色,并在 $background 中設(shè)置了背景色,下一步就是計(jì)算每種顏色的相對(duì)亮度。 W3C 提供了一個(gè)算法 用以計(jì)算顏色的相對(duì)亮度。
- 對(duì)于 sRGB 色彩空間,一種顏色的相對(duì)亮度定義為:
 
- L = 0.2126 * R + 0.7152 * G + 0.0722 * B
 
- if RsRGB <= 0.03928 then R = RsRGB/12.92
 - else R = ((RsRGB+0.055)/1.055) 2.4
 - if GsRGB <= 0.03928 then G = GsRGB/12.92
 - else G = ((GsRGB+0.055)/1.055) 2.4
 - if BsRGB <= 0.03928 then B = BsRGB/12.92
 - else B = ((BsRGB+0.055)/1.055) 2.4
 
- RsRGB = R8bit/255
 - GsRGB = G8bit/255
 - BsRGB = B8bit/255
 
由于 Zenity 以 rgb(R,G,B) 的格式返回顏色值,因此腳本可以輕松拉取分隔開(kāi)的 R、B 和 G 的值以計(jì)算相對(duì)亮度。AWK 可以使用逗號(hào)作為字段分隔符(-F,),并使用 substr() 字符串函數(shù)從 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)}' )
 
有關(guān)使用 AWK 提取和顯示數(shù)據(jù)的更多信息,查看 AWK 備忘表
最好使用 BC 計(jì)算器來(lái)計(jì)算最終的相對(duì)亮度。BC 支持計(jì)算中所需的簡(jiǎn)單 if-then-else,這使得這一過(guò)程變得簡(jiǎn)單。但是由于 BC 無(wú)法使用非整數(shù)指數(shù)直接計(jì)算乘冪,因此需要使用自然對(duì)數(shù)替代它做一些額外的數(shù)學(xué)運(yùn)算:
- 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
 
這會(huì)將一些指令傳遞給 BC,包括作為相對(duì)亮度公式一部分的 if-then-else 語(yǔ)句。接下來(lái) BC 打印出最終值。
計(jì)算對(duì)比度
利用文本顏色和背景顏色的相對(duì)亮度,腳本就可以計(jì)算對(duì)比度了。 W3C 確定對(duì)比度 是使用以下公式:
(L1 + 0.05) / (L2 + 0.05),這里的 L1 是顏色較淺的相對(duì)亮度, L2 是顏色較深的相對(duì)亮度。
給定兩個(gè)相對(duì)亮度值 $r1 和 $r2,使用 BC 計(jì)算器很容易計(jì)算對(duì)比度:
- 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 語(yǔ)句確定哪個(gè)值($r1 或 $r2)是較淺還是較深的顏色。BC 執(zhí)行結(jié)果計(jì)算并打印結(jié)果,腳本可以將其存儲(chǔ)在變量中。
最終腳本
通過(guò)以上內(nèi)容,我們可以將所有內(nèi)容整合到一個(gè)最終腳本。 我使用 Zenity 在文本框中顯示最終結(jié)果:
- #!/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
 - W3C 說(shuō)明:
 - 1.4.3 對(duì)比度(最小值):文本和文本圖像的視覺(jué)呈現(xiàn)方式的對(duì)比度至少為 4.5:1,但以下情況除外:(AA 級(jí))
 - 大文本:大文本和大文本圖像的對(duì)比度至少為 3:1;
 - 附帶說(shuō)明:作為非活動(dòng)用戶界面組件一部分,純裝飾的,任何人都不可見(jiàn)或圖片的一部分包含特定的其他可視內(nèi)容的文本或文本圖像沒(méi)有對(duì)比度要求。
 - 小示意圖:徽標(biāo)或商標(biāo)名稱中的文本沒(méi)有最低對(duì)比度要求。
 - 1.4.6 對(duì)比度(增強(qiáng)):文本和文本圖像的視覺(jué)表示具有至少 7:1 的對(duì)比度,但以下情況除外:(AAA 級(jí))
 - 大文本:大文本和大文本圖像的對(duì)比度至少為 4.5:1;
 - 附帶說(shuō)明:作為非活動(dòng)用戶界面組件一部分,純裝飾的,任何人都不可見(jiàn)或圖片的一部分包含特定的其他可視內(nèi)容的文本或文本圖像沒(méi)有對(duì)比度要求。
 - 小示意圖:徽標(biāo)或商標(biāo)名稱中的文本沒(méi)有最低對(duì)比度要求。
 - EOF
 - ) | zenity --text-info --title='Relative Luminance' --width=800 --height=600
 
最后,我希望提供有關(guān) W3C 建議的參考信息,以提醒自己。
Zenity 顏色選擇器完成了所有解釋顏色的艱苦工作,用戶可以通過(guò)單擊色輪或輸入值來(lái)選擇顏色。 Zenity 接受網(wǎng)站上使用的標(biāo)準(zhǔn)十六進(jìn)制顏色值,例如 #000000 或 #000或 rgb(0,0,0)(所有這些均為黑色)。這是白色背景上的黑色文本的示例計(jì)算:
Zenity 還識(shí)別標(biāo)準(zhǔn)的顏色名稱,如“cadetblue”、“orange”或“gold”。在Zenity 中輸入顏色名稱,然后點(diǎn)擊 Tab 鍵,Zenity 會(huì)將顏色名稱轉(zhuǎn)換為十六進(jìn)制顏色值,如以下示例中對(duì)金色背景上的黑色文本的計(jì)算:























 
 
 













 
 
 
 