「きれい」は好みだが、「読める」は測れる。 薄い灰色の文字は良いモニタでは平気に見えて、 日中の屋外ではスマートフォンから消える — 目で選んでいれば、いつか必ずそうなる。
python3 addons/gohud/tools/check_contrast.py
| 対象 | 必要な比 |
|---|---|
| 本文の文字 | 4.5 : 1 |
| 大きな文字(24px 以上) | 3 : 1 |
| アクセントの枠とアイコン | 3 : 1 |
| 装飾の枠 | 2 : 1 — WCAG は装飾に 3:1 の規則を課していない |
| 隣り合う面 | 1.12 : 1 — カードが背景と別物だと分かる程度 |
同系色の文字を同系色の淡い面に載せる
この落とし穴は、このコードベースで3度現れた — 押されたボタン(アクセントのパネルにアクセントの文字)、 危険ボタン、そしてチップだ。色見本の上ではよく見えるのに、測った瞬間に崩れる。 2つが同じ色相を共有していて、明度の差がないからだ。
だからラベルの色は手で選ばない。テーマのビルダーと GoSkin はそれぞれ、文字が実際に載る
パネルの上でしきい値を超えるまで明度だけを押し上げる。色相と彩度は残るので、パレットは持ち味を保ち、
変更してもコントラストは保たれる。
文字として読む色と、面として塗る色は求めるものが逆だ
ライトテーマでは、警告色は文字として読めるよう暗くしなければならない(#96500A)。
バーの塗りがそれを受け継ぐと、経験値バーは茶色になる。色だけでは直せない。黄色はそもそも明るく、
灰色の溝に対して 3:1 をまったく満たさないし、溝を暗くするともっと悪くなる(1.52 → 1.06)。
そこで両者を切り離した。色は鮮やかなまま — パレットは warning_vivid のような
塗り専用の色を持つ。コントラストは縁が担う — GoSkin は、溝に対して 3:1 に届かない塗りに
1dp の輪郭を描く。こうして「どれだけ溜まっているか」は読めるままになる。
MY_LIGHT = dict(
warning=hexc("9A5407"), # 文字として読む色
warning_vivid=hexc("F2A007"), # バーに塗る色
)
*_vivid がないまま塗りが暗くなると、ビルダーは
the bar looks drab — add warning_vivid to the palette と出力する(ビルダーが実際に出す文言)。
黙って劣化していた場所が、いまは声を上げる。
浮かぶパネルは、背後に何があるか知りようがない
HUD はゲームの上に描かれる — 雪原かもしれないし、洞窟かもしれない。パネルが半透明なら背後のものが
透けてパネルの色そのものを変え、文字のコントラストまで道連れにする。不透明度 82% では、明るい背景の上で
ダークテーマの控えめな文字が 3.74:1 まで落ちた — 最低基準を下回っている。
そこで半透明のパネルは純白と純黒を背後に置いて測る。ゲームの場面が出しうる最悪がその2つだからだ。 同梱テーマの HUD パネルは、ガラスのような見え方を保ったまま基準を通る不透明度 (92%) にしてある。
同じ理由でアイコンの色も固定していない。クイックスロットのグリフは白で決め打ちされていて、
ライトテーマで 1.11:1 と測れた — いまはラベルとまったく同じように、載っているパネルに従う。
check_contrast.py はテーマファイルを読む。
スキンが実行中に混ぜる色(チップ、スロット)は、Godot の中で走るテストスイートの
skin contrast の節が測る。