文字色と背景色の差は十分?JavaScriptでWCAG 2.2のコントラスト比を比べる

プログラミング・Web開発カテゴリを表すパンダのイラスト プログラミング・Web開発

この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。W3CのWCAG 2.2とMDNの公式資料を確認し、架空の色でコントラスト比を計算する教材を作りました。

検証ステータス:📘 公式仕様確認・隔離V8計算10条件PASS/実ブラウザー・GitHub Pages公開URL・WordPress表示は未確認

「薄いグレーの文字はおしゃれだけれど、読みづらい気がする」。Webサイトや業務画面の色を決めるとき、感覚だけでは判断しにくいものです。今回は文字色と背景色を1か所ずつ変え、見た目の差を数値で比較します。APIキーも個人情報も不要です。

まず試す:色を変えると判定はどうなる?

項目今回の条件
対象JavaScriptが使えるブラウザー、sRGBの不透明な2色
使用技術HTMLの色選択、JavaScriptの相対輝度計算
費用・通信ライブラリ・CDN・API不要。入力色の外部送信なし
検証計算ロジックの隔離V8テスト10条件PASS。画面実動作は未確認

Daily Code:完成コード・README・テスト

GitHub Pagesデモ(公開URLへの到達・実動作は未確認)

手元で確実にファイルを確認するなら、上の固定コミットから web/contrast-lab/ を取得し、同じフォルダーの index.html を開いてください。表示されない環境ではリポジトリのルートで python3 -m http.server 8000 を実行し、ローカルの /web/contrast-lab/ を開きます。実ブラウザーでの成功はまだ確認していません。

操作は3つです。

  1. 「黒と白」を押して、コントラスト比とAA判定を見る。

  2. 「灰色 #777777」を押し、AA通常文字:未達になることを確認する。

  3. 「灰色 #767676」を押し、AA通常文字:適合に変わることを比較する。

これはコード上の期待結果です。画面表示や色の見え方はブラウザー・端末で別途確認してください。

観察ポイント:少し暗くしただけで判定が変わる

文字色/背景色計算上の比率AA通常文字(4.5:1)
黒 #000000 / 白 #ffffff21.00:1適合
灰色 #777777 / 白約4.48:1未達
灰色 #767676 / 白約4.54:1適合

見本の2種類の灰色は非常によく似ています。それでも、閾値4.5をまたぐと判定は変わります。画面の表示は小数第2位に丸めていますが、合否判定には丸め前の数値を使っています。「4.49を4.5と表示したから適合」とする誤判定を避けるためです。

「文字色と背景色を交換」を押しても、コントラスト比は同じになる設計です。比率は明るい側と暗い側の相対輝度から計算するため、順番を入れ替えても数値は変わりません。ただし、読みやすさの感じ方や文字の太さは別問題です。

なぜ4.5:1なのか:WCAGの基準を整理

W3CのWCAG 2.2には、文字のコントラストに関する達成基準があります。通常文字のレベルAAは4.5:1以上、大きな文字のレベルAAは3:1以上です。より厳しいレベルAAAでは通常文字7:1以上、大きな文字4.5:1以上が基準です。大きな文字の定義や例外もあるので、単に画面上の見出しというだけで「大きな文字」に分類しないでください。

対象AAAAA
通常の文字4.5:17:1
大きな文字3:14.5:1

今回の計算は、各色の赤・緑・青を0〜1の値に変換し、sRGBのガンマ補正をした後、相対輝度を求めます。明るい側の輝度をL1、暗い側をL2とすると、比率は (L1 + 0.05) / (L2 + 0.05) です。単純にRGB値の差を引き算しているわけではありません。

flowchart LR
    A["文字色と背景色"] --> B["16進RGBを読み取る"]
    B --> C["sRGBを線形化"]
    C --> D["相対輝度を計算"]
    D --> E["明暗の比率を計算"]
    E --> F["AA・AAAの閾値と比較"]

この図は教材の計算順序を簡略化したものです。色の見た目そのものをシミュレーションしているわけではありません。

JavaScriptの核心はここだけ

完成版の contrast.js では、RGB各成分を次の式で変換します。

function channel(n) {
  const s = n / 255;
  return s <= 0.04045 ? s / 12.92
    : Math.pow((s + 0.055) / 1.055, 2.4);
}

変換後のRGBを 0.2126 * R + 0.7152 * G + 0.0722 * B で合成すると相対輝度になります。入力は #RRGGBB の6桁だけに制限し、不正な値は例外にします。表示用のDOM更新には textContent を使い、入力をHTMLとして解釈しません。

全コードは固定コミットのDaily Codeにあります。教材内の test.mjs はNode標準テストの例ですが、今回実行したのは隔離V8での計算ロジック10条件であり、node --test の実行成功を主張するものではありません。

1か所だけ変更してみる

まず背景を白 #ffffff に固定します。文字色を #777777 から #767676 に変えてください。1段階だけ暗い色にすることで、計算上の比率は約4.48から約4.54に変わります。

次に背景を変えたい場合は、文字色を固定して試します。複数条件を一度に変えると、どちらが原因で読みやすさや判定が変化したのか分からなくなります。業務画面のデザインレビューでも、文字色と背景色を別々に比較すると説明しやすくなります。

うまく動かないとき

症状まず確認すること次の対処
数字が「—」のままJavaScriptが有効か開発者ツールでcontrast.jsとapp.jsの読み込みを確認
デモURLが開かないGitHub Pagesの公開状態は未確認固定コミットからローカル起動
数値は合格なのに読みにくいフォントの細さ・サイズ・背景画像実画面で文字サイズや背景を再評価
表示比率と境界判定が違って見える表示は小数第2位に丸める丸め前の計算値で判定しているか確認
色が選べないブラウザーの色入力対応別の対応ブラウザーで確認。未検証OSでの成功は保証しない

仕事で使うなら:レビューの入口にする

例えば社内システムの「入力必須」「エラー」「補足説明」の文字色を見直すとき、まずこの教材で候補の文字色と背景色を比較します。数値が閾値を下回った組合せを見つけたら、デザイン担当と色の変更案を話し合えます。変更後は実画面で、フォント、画面倍率、フォーカス表示、画像上の文字、透明度なども確認してください。

この教材だけでWebサイト全体のWCAG適合を宣言することはできません。 非テキストのUI部品、画像・グラデーション背景、透明色、操作性、スクリーンリーダーなどは別の検査が必要です。色だけに意味を持たせず、今回の合否も「適合」「未達」と文字で示しています。

公式資料

図で考える:判定値が合格でも読めるとは限らない

コントラスト比は「人が必ず読みやすい」と約束する魔法の値ではありません。W3CのWCAGに定められた特定の達成基準を、一定の条件で確認するための数値です。文字のサイズ、太さ、背景の変化、画像に重なっているかどうかで、実際の読みやすさや調査対象は変わります。

flowchart TD
    A["文字と背景の色を決める"] --> B["不透明な2色の相対輝度を計算"]
    B --> C["丸め前のコントラスト比を求める"]
    C --> D{"対象文字の基準"}
    D -->|"通常文字・AA"| E["4.5対1以上か確認"]
    D -->|"大きな文字・AA"| F["3対1以上か確認"]
    D -->|"AAA"| G["別の厳しい基準で確認"]
    E --> H["実画面のサイズ・太さ・背景も確認"]
    F --> H
    G --> H

この図で重要なのは、数値を出したら終わりではないことです。教材は不透明な2色のsRGBを前提にしています。半透明の文字や背景画像が重なる画面では、入力した色の組み合わせだけでは実際に表示される色を代表できません。たとえば灰色の文字を白い背景で測って合格しても、背後が写真に切り替わるページでは文字部分の背景色が変わります。対象箇所の実際の表示条件を確かめる必要があります。

4.48と4.54の「わずかな差」をどう使う?

教材にある#777777と#767676は一段階の差しかなく、同じ白い背景に置くと人の目では違いを説明しにくいかもしれません。しかし計算値は4.5:1の境界をまたぎます。ここではデザインの好みで選ぶのではなく、元の色、変更後の色、計算値、対象文字の基準を記録すると、変更理由を共有しやすくなります。

画面に表示する比率を小数第2位へ丸めても、判定処理では丸め前の値を使います。たとえば丸められた表示だけを見て4.5以上と判定すると、境界の手前にある数値を誤って合格させることがあります。コードで判定する値と人に見せる値を区別し、境界近くでは元の計算を確認します。

実務での確認対象を一つずつ増やす

架空の予約システムで、「入力必須」の補足文字を薄い灰色にしているとします。最初に文字色と背景色のコントラスト比を測り、基準未達なら候補の色を少し変えて比較します。その後、同じ文字がボタンの上、入力欄の下、エラーメッセージなど複数の背景に配置されていないかを確認します。一つの画面で合格した色が別画面でも同じ条件とは限りません。

また、色の違いだけで「エラー」「正常」を伝える設計には別の問題があります。赤と緑を区別しにくい利用者、モノクロ印刷で確認する利用者、スクリーンリーダーで内容を読む利用者に伝わるよう、文字ラベルや記号など別の情報も付けます。文字コントラストの達成基準を満たすことは、Webアクセシビリティの一部分にすぎません。

この数値では調べられないこと

画像上の文字、透明度、グラデーション、細いフォント、拡大表示、フォーカスの視認性、操作可能な部品の境界などは、今回の教材だけで完全に確認できません。文字以外のユーザーインターフェース部品には別の達成基準も関係します。したがって、計算ツールの結果を根拠に「サイト全体がWCAG 2.2に適合した」と宣言してはいけません。

デザインレビューではまず候補色を数値で絞り、次に実画面を複数の状態で確認します。数値と実際の使い勝手の両方を扱うことで、開発者とデザイナー、利用部門が話し合いやすくなります。技術的な判定が、そのまま人の利用体験のすべてを表すわけではない、という気づきがこの実験の目的です。

まとめ

色の見た目だけでは分からない差を、入力→数値→閾値→一条件変更の順に観察できるのがこの教材の狙いです。まずは黒と白、次に2種類の灰色を比べてみてください。結果を実務で使うときは、実画面での読みやすさも必ず合わせて確認しましょう。

文書情報

記事タイトル
文字色と背景色の差は十分?JavaScriptでWCAG 2.2のコントラスト比を比べる
作成日
更新日
Source URL
https://papanda925.com/?p=18460

ライセンス: 本記事のうち、当サイトが権利を有する本文・自作図表は、特記なき限り CC BY 4.0 で利用できます。生成AIを活用して作成・編集した内容を含みます。コードについて、別途ライセンス表示またはリンク先GitHubリポジトリのライセンスがある場合は、その条件を優先します。引用・第三者資料・画像・商標等は本ライセンスの対象外です。 利用ポリシー

タイトルとURLをコピーしました