網頁設計中,文本是最經常使用的元素之一,文本易讀性很是重要,咱們都但願頁面更加清晰易讀,而顏色在文本易讀性中起到了相當重要的做用。css
文本和背景顏色有一個「對比度」,瞭解並能正確調整這個對比度,將會讓你的頁面更加清晰易讀,進而提升閱讀效率和閱讀體驗。html
在缺少專業設計的頁面中,咱們常常見到下面這樣的畫面:android
這是公司的某內部系統: ios
公司某內部工具: git
有沒有以爲上面的文本特別刺眼,難以識別?github
上面的兩個案例,本質上都是文本色與背景色的「對比度」不足致使的,足夠的色彩「對比度」可以讓文字和圖片更易於閱讀和理解。web
「對比度」是指顯示屏上兩種相鄰顏色之間的亮度或發出光線的強度的差別計算值。這個比值的範圍在 1 到 21 之間(一般寫爲 1:1 到 21:1);該值越大,則對比度越高。算法
實際上,W3C 的 Web 無障礙推動組織制定了 Web 內容無障礙指南(WCAG),這個指南涉及了一些建議,這些建議可以使 Web 內容更容易訪問。遵循這些原則,可以讓內容更易爲廣大殘障人士所接受,包括失明和低視力、失聰和重聽、學習障礙、認知障礙、行動不便、言語殘疾、光過敏患者和這些病症的複合患者。遵循這些原則也可以讓普通用戶更容易訪問 Web 內容。瀏覽器
簡單總結一下這個標準:sass
對比度等級 | 普通文本 | 大型文本 |
---|---|---|
AA | 4.5:1 | 3:1 |
AAA | 7:1 | 4.5:1 |
對比度等級:
字體大小的分界線:
那麼如何實現符合 WCAG 規範的對比度呢?如何在項目中漸變快捷地進行調整呢?
有不少工具能夠調整對比度,這裏列舉一些我使用過的工具:
一個在線的,計算任意兩種有效 CSS 顏色之間對比度的工具。
兩側分別爲文本顏色與背景色,中間一個醒目的圓盤,顯示兩者的對比度,鼠標移動到這個圓盤上能夠查看該對比度符合 AA/AAA 對比度標準。
對於開發的同窗來講,這種方式也很快捷方便。新版的 Chrome 瀏覽器加強了 CSS 的調色功能:
打開控制檯,選中一個 文本元素 而後在 Styles 中找到 color 屬性,點擊 顏色值,能夠看到一個調色板。
而後點擊調色板的 Contrast radio 選項,展開對比度計算工具,能夠看到上方的調色板出現一條白線,這條白線就是符合 AA 級對比度標準的臨界值。調色板中的圓圈就是當前選中的色值,拖動這個色值便可調整文本顏色,這時下方的對比度計算工具進行了實時計算:
經過構建工具便可在構建時進行對比度的驗證,從而保證 UI 中的文本易讀性符合標準。
有一些開源的 JS 庫能夠進行對比度的計算,這裏我找到了一個很好用的庫: TinyColor, 經過 readability 函數計算兩個顏色的對比度:
tinycolor.readability("#000", "#000"); // 1
tinycolor.readability("#000", "#111"); // 1.1121078324840545
tinycolor.readability("#000", "#fff"); // 21
複製代碼
經過 isReadable 函數判斷是否符合 AA/AAA 級對比度標準:
tinycolor.isReadable("#000", "#111", {}); // false
tinycolor.isReadable("#ff0088", "#5c1a72",{level:"AA",size:"small"}); //false
tinycolor.isReadable("#ff0088", "#5c1a72",{level:"AA",size:"large"}), //true
複製代碼
經過 JS 進行對比度的計算,舉個栗子,一個最多見的場景: 手機頂部狀態欄中文本很是顯眼,背景色多變,但文本色的正確搭配每每被忽視,下圖是咱們 APP 中某個頁面的狀態欄:
能夠看到狀態欄的文本是黑色,而 header 中的文本顏色又是白色,通常來講狀態欄的顏色設置爲黑色或白色(iOS 中只能設置這兩種顏色),這時狀態欄的顏色最好根據 js 來計算,人爲設置黑色或白色容易搭配不當或者遺漏配置。
在彩色背景上使用灰色文本會下降對比度:
最先是在 Material Design 的設計規範中看到的這個技巧,使用透明的黑白色文本和彩色背景的時候,文本顏色會混合成相應的深色,例如上圖中的深粉色。這樣作的好處是背景顏色變化的時候文本顏色會自動混合成對應的深色,沒必要改變文本的顏色值。
頁面中色彩不宜過多,謹慎使用彩色文本,應該把彩色留給按鈕、連接、開關等組件,這樣作的好處是文本層次鮮明,失去控制的過多色彩會讓內容缺少重點。
正文使用黑白色(在大段的正文中使用彩色文本不利於閱讀)
按照功能的重要性,爲文本制定不一樣半透明度的規範,從而對不一樣層次信息的對比度加以區分。
使用不一樣半透明度的文本,用於區分標題、正文、描述文本、提示文本和icon。這樣作可讓讀者閱讀起來有必定的優先級關係,可讓信息層次鮮明,有助於用戶理解關鍵信息,減小閱讀時候的疲勞感。
若是背景的色彩比較複雜(如漸變色、圖案等),則能夠根據平均值來做爲背景色計算對比度。
若是背景色的色彩差別較大,則應在文本和背景之間添加遮罩。
即上文提到的使用 TinyColor 工具進行精確計算,在構建工具中驗證。
雖然 WCAG 提出了 AA/AAA 級對比度標準,可是實際使用時應從用戶角度出發,根據實際場景肯定是否須要更強烈的對比度,舉幾個例子:
這段代碼用 sass 實現了若干函數,其中:
** 1. @function mdc-theme-contrast-tone ** 傳入一個顏色值,返回該顏色背景上應該使用的顏色爲 light / dark 顏色
** 2. @function mdc-theme-tone ** 傳入一個顏色值,返回該顏色爲 light / dark 顏色,核心代碼:
// 傳入的顏色值爲 $color
$lightContrast: mdc-theme-contrast($color, white); // 計算傳入顏色和白色的對比度
$darkContrast: mdc-theme-contrast($color, rgba(black, .87)); // 計算傳入顏色和黑色的對比度
$minimumContrast: 3.1; // 設置最小對比度
@if ($lightContrast < $minimumContrast) and ($darkContrast > $lightContrast) {
// 傳入的顏色值和白色的對比度小於最小對比度 而且 和黑色的對比度更高
@return "light"; // 咱們認爲傳入的顏色是淺色
} @else {
// 咱們認爲傳入的顏色是深色
@return "dark";
}
複製代碼
3.👆 上面的代碼中用到了計算對比度的函數 mdc-theme-contrast 也在這段代碼中,對比度是這樣計算的:
// 計算顏色的相對亮度(relative luminance)
@function mdc-theme-luminance($color) {
$red: nth($mdc-theme-linear-channel-values, red($color) + 1);
$green: nth($mdc-theme-linear-channel-values, green($color) + 1);
$blue: nth($mdc-theme-linear-channel-values, blue($color) + 1);
@return .2126 * $red + .7152 * $green + .0722 * $blue;
}
// 計算兩個顏色的對比度(contrast ratio)
@function mdc-theme-contrast($back, $front) {
$backLum: mdc-theme-luminance($back) + .05;
$foreLum: mdc-theme-luminance($front) + .05;
@return max($backLum, $foreLum) / min($backLum, $foreLum);
}
複製代碼
這裏用到了一個對比度計算公式: www.w3.org/TR/WCAG20-T…
能夠看到一些有趣的參數:
@return .2126 * $red + .7152 * $green + .0722 * $blue;
複製代碼
相同的色值,綠色要顯得亮一些,相反藍色要顯得暗一些。
Material Design 在計算傳入顏色和黑色的對比度時,傳入的是一個帶有半透明度的色值,實際上在執行時會按照純黑色(不帶有半透明度)進行解析。
$darkContrast: mdc-theme-contrast($color, rgba(black, .87)); // 計算傳入顏色和黑色的對比度
複製代碼
我理解的 rgba(black, .87) 指的是 Material Design 規定的正文字體顏色(深色),所以這裏按照半透明色進行解析會更好一些,這樣咱們判斷顏色是深色仍是淺色時的依據就是頁面上最深的文本顏色 (#000 87%) 和最淺的背景顏色 (#fff 100%) 了。
用 js 來實現這個混合的過程 (依賴 tinycolor):
// Alpha 合成 支持前景色半透明
function mixColor(front, back) {
var rgbFront = tinycolor(front).toRgb();
var rgbBack = tinycolor(back).toRgb();
var alphaFront = rgbFront.a;
var mixR = alphaFront * rgbFront.r + (1 - alphaFront) * rgbBack.r;
var mixG = alphaFront * rgbFront.g + (1 - alphaFront) * rgbBack.g;
var mixB = alphaFront * rgbFront.b + (1 - alphaFront) * rgbBack.b;
var res = tinycolor({ r: mixR, g: mixG, b: mixB }).toHexString();
return res;
}
複製代碼
Alpha 合成算法來自: 維基百科 - Alpha 合成
Material Design 中最小對比度是寫死的 3.1,不知道爲何沒有設置爲 AA/AAA 級對比度標準,這裏能夠傳入參數來指定最小對比度:
function contrast(color, contrast) {
if (color === 'light' || color === 'dark') return color;
var minimumContrast = contrast || 3.5;
var lightContrast = getContrast(color, '#fff');
var darkContrast = getContrast(color, '#000');
if (lightContrast < minimumContrast && darkContrast > lightContrast) {
return 'light';
} else {
return 'dark';
}
}
複製代碼
上文提到的 Material Design 的源碼包含的幾個函數,在 TinyColor 這個工具裏都有實現。
我按照 Material Design 的實現思路,用 js 實現了一遍,增長了上文提到的兩個優化點 (支持半透明度顏色混合 / 支持調節最小對比度): 源碼地址