色とコントラスト:相対輝度はチャンネルの平均ではない

記法の相互変換は入口にすぎません。本当の罠は WCAG のコントラストで、ガンマを戻してから重み付けする必要があります。黒文字か白文字かの判断も閾値ではありません。

三つの記法、三つの役割

hex は受け渡しの形式、rgb はチャンネル演算、hsl は色を選ぶときに直感に合う唯一の記法です。変換自体は難しくありませんが、往復の精度でつまずきます。hsl の色相は浮動小数なので、丸めてから戻すと色が変わります。中間表現は浮動小数のまま保ち、整形は出力時だけにします。

相対輝度はチャンネルの平均ではない

WCAG のコントラストの第一歩は、sRGB のチャンネルを線形値へ戻すことです。ガンマの近似を使います。

c = channel / 255
linear = c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ^ 2.4
L = 0.2126 * R + 0.7152 * G + 0.0722 * B

コントラストは (L1 + 0.05) / (L2 + 0.05) で、明るい側を分子にします。

ガンマを飛ばして RGB をそのまま平均するのは、この種のツールで最も多い不具合です。出てくる数字はそれらしく見えますが、中間調で仕様から外れ、AA や AAA の判定も信用できなくなります。

しきい値

本文は 4.5:1(AA)または 7:1(AAA)、大きな文字は 3:1 と 4.5:1 に緩和されます。ツールは数字だけでなく等級を表示します。規範と並べなければ数字は意味を持たないからです。

スケールは白黒への混色ではない

50 から 900 のスケールを白と黒へ単純に補間すると、中間の段が潰れて分離感が失われます。色相と彩度を固定し、知覚的な明度で均等にサンプリングすると、隣り合う段の見た目の差をほぼ一定に保てます。

黒文字か白文字か

よくある規則は明度が 128 を超えるかどうかです。これは黄緑の領域で誤答を返します。明度は中から高ですが、白とのコントラストは依然として不足しています。確実な方法は両方の候補を計算し、コントラストが大きい方を選び、数値を正直に示すことです。

既知の値による裏付け

この種の計算は既知の値の確認に向いています。黒と白はちょうど 21、同じ色同士は 1、三つの記法を往復すれば元の値に戻る。この三つを自検に入れておけば、リファクタリングのたびに式を導き直す必要はありません。

← 記事一覧に戻る

コメント

…