色とコントラストの話
コントラスト比の計算式についてメモ。UIデザイン関係者はご存知のとおり背景色と文字の間に十分なコントラストがあることはとても大事で、WCAGのガイドラインでは下記の基準が決められています。
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.
最低でも4.5:1のコントラスト比(contrast ratio)を満たすこと。ただし大きいテクスト*は3:1でOK。アクティブでないコンポーネントや装飾、ロゴの一部などはこの基準から除外。
Web上のツールやSketch、Figmaのプラグインなどを使って検証するのが一般的で実用上はそれでなんの問題もないと思うのですが、なんかそれだけだとブラックボックス的で気持ちが悪いのでまとめました。
輝度と明度
コントラスト比の計算には相対輝度 (Relative Luminance)を使います。デザイナーならば明度(Brightness)という言葉の方が馴染みがありますね。色は色相(Hue)、彩度(Saturation)、明度(Brightness)の三つの値で表すことができます。
Photoshopが使っている計算式を使うと明度は
brightness = max(R, G, B) / 255 * 100%
と簡単に計算できます。RGBの一番大きいやつを取るだけ。ただこの方法だと黄色(255, 255, 0)と青(0, 0, 255)が同じ明度になってしまいます。実際には黄色の方が明るく感じられると思うので、この式は人間の感覚をあまりうまく表せてはいないと言えます。
ではWCAGの基準になっている相対輝度はどのように計算するのでしょう。
まずRGBごとに計算
まずRGBそれぞれごとに
s = (V / 255) # VはR, G, Bを8bit値(0-255)で表したもの
t = s / 12.92 IF s < 0.003928 ELSE (s + 0.055) / 1.055) ^ 2.4
という無駄にややこしい計算をします。式だけだとピンと来ないのでざっくりグラフにするとこんな感じ。
入力が小さい時はかなり小さな出力に留まり、入力が大きくなるにつれて急に出力も上がるカーブになります。直線的な入力に対して人間の知覚を表す出力は指数関数的。
こうしてRGBごとに0から1の値が得られるので、今度はこの3つの値を
Relative Luminance = 0.2126 * R + 0.7152 * G + 0.0722 * B
と足し合わせます。この式は上でも出てきた青よりも黄色の方が明るく感じる件を表しています。RGBをグレースケールに変換するときなどに使います。
詳しくはsRGBについて調べるといろいろ書いてあるので読んでみましょう。
比を求める
ここまでできたらあとは明るい色と暗い色の値を比べるだけですが、こんな式になっています。
(L1 + 0.05) / (L2 + 0.05)
0.05を足すのはゼロ割を防ぐためかな。例えば白(255, 255, 255)の文字の対して赤(255, 0, 0)の背景の場合、比は (1 + 0.05) / (0.2126 + 0.05) でおよそ 4:1 、WCAGの基準は満たせていないことになります。
自己満足したので以上!WCAGの正式なアルゴリズムはこちら。
余談
この基準はCRTの時代に設けられたのでLSDやOLEDだとまた違くない?とか細かい話はあるのですがそもそも機器ごとや環境の差は避けられないのでざっくり基準としては良いと思っています。でもそのうち誰かがちゃんと見直すべきだとも思っています。
*「大きいテクスト」とは何か、という問題は結構根が深いのでいつか別途。18pt 以上か14pt Bold以上なら大きい、ということになっているのですが、1ptの大きさってデバイス毎に違うし使うときの距離とか、いろいろ。
この記事が気に入ったらサポートをしてみませんか?