Web アクセシビリティガイド
WCAG 2.1 準拠を目標としたフレームワーク非依存のアクセシビリティ設計・実装ガイド。
WCAG 2.1 の 4 原則
| 原則 | 意味 | 主な要件 |
|---|---|---|
| 知覚可能 (Perceivable) | 情報を知覚できる | テキスト代替、キャプション、コントラスト |
| 操作可能 (Operable) | UI を操作できる | キーボード操作、十分な時間、発作防止 |
| 理解可能 (Understandable) | 情報と操作が理解できる | 読みやすさ、予測可能、入力支援 |
| 堅牢 (Robust) | 支援技術と互換性がある | 適切なマークアップ、名前と役割 |
準拠レベル
code
Level A: 最低限の要件(必須) Level AA: 推奨レベル(一般的な目標) Level AAA: 最高レベル(全ページ準拠は非現実的) → 通常は Level AA 準拠を目標にする
セマンティック HTML
ランドマーク
html
<header> → バナー(サイトヘッダー) <nav> → ナビゲーション <main> → メインコンテンツ(ページに1つ) <aside> → 補足コンテンツ <footer> → フッター <section> → セクション(見出し付き) <article> → 独立したコンテンツ
見出し階層
code
- h1 はページに 1 つ - 階層を飛ばさない(h1 → h3 は NG) - 見出しだけで文書構造が理解できるように - 装飾目的で見出しタグを使わない
インタラクティブ要素
code
原則: ネイティブ HTML 要素を優先する ✅ <button> → クリック可能な操作 ✅ <a href=""> → ナビゲーション ✅ <input>, <select>, <textarea> → フォーム入力 ❌ <div onclick=""> → ボタンの代替(キーボード操作不可) ❌ <span> でリンク模倣 → スクリーンリーダーが認識しない
ARIA パターン
ARIA の基本原則
code
1. ネイティブ HTML で解決できるなら ARIA は不要 2. ネイティブのセマンティクスを上書きしない 3. インタラクティブな要素はキーボード操作可能にする 4. focusable な要素に role="presentation" を使わない 5. すべてのインタラクティブ要素にアクセシブルな名前を付ける
よく使う ARIA 属性
| 属性 | 用途 | 例 |
|---|---|---|
| aria-label | 要素に名前を付ける | <button aria-label="メニューを閉じる">×</button> |
| aria-labelledby | 別要素で名前を定義 | <div aria-labelledby="title-id"> |
| aria-describedby | 説明を関連付け | <input aria-describedby="help-text"> |
| aria-expanded | 展開状態 | <button aria-expanded="false"> |
| aria-hidden | 支援技術から隠す | <span aria-hidden="true">装飾</span> |
| aria-live | 動的更新の通知 | <div aria-live="polite"> |
| aria-required | 必須フィールド | <input aria-required="true"> |
| aria-invalid | エラー状態 | <input aria-invalid="true"> |
| role | 要素の役割を定義 | <div role="alert"> |
詳細: references/aria-patterns.md
キーボードナビゲーション
必須のキーボード操作
| キー | 動作 |
|---|---|
| Tab | 次のフォーカス可能な要素へ |
| Shift + Tab | 前のフォーカス可能な要素へ |
| Enter / Space | ボタン/リンクの実行 |
| Escape | モーダル/ポップアップを閉じる |
| 矢印キー | ラジオボタン、タブ、メニュー内の移動 |
フォーカス管理
code
原則: - フォーカスインジケーターを常に表示する(outline: none 禁止) - フォーカス順序が論理的であること(tabindex の乱用を避ける) - tabindex="0": 自然な順序でフォーカス可能にする - tabindex="-1": プログラムでフォーカスするが Tab では到達しない - tabindex > 0: 使用禁止(順序が混乱する) フォーカストラップ: - モーダル表示時はモーダル内にフォーカスを閉じ込める - モーダルを閉じたら元の要素にフォーカスを戻す
スキップリンク
code
ページ先頭に「メインコンテンツへスキップ」リンクを配置 → キーボードユーザーがナビゲーションを飛ばせる → 通常は非表示、フォーカス時に表示
フォームアクセシビリティ
ラベル
code
必須:
- すべての入力フィールドに関連付けられたラベルを付ける
- <label for="id"> または aria-label / aria-labelledby
placeholder はラベルの代替にならない:
❌ <input placeholder="メールアドレス">
✅ <label for="email">メールアドレス</label>
<input id="email" placeholder="example@mail.com">
エラー表示
code
原則: - エラーメッセージをフィールドに関連付ける(aria-describedby) - エラー発生時にフォーカスをエラー箇所に移動 - 色だけでエラーを示さない(アイコン + テキストも使う) - aria-invalid="true" でエラー状態を伝える - エラーサマリーをフォーム上部に表示(複数エラー時)
バリデーション
code
- リアルタイムバリデーションは aria-live で結果を通知 - 必須フィールドは aria-required="true" + 視覚的な印 - 入力形式のヒントを aria-describedby で提供
カラーコントラスト
code
WCAG AA 基準: - 通常テキスト: コントラスト比 4.5:1 以上 - 大きなテキスト(18px 以上 or 14px bold): 3:1 以上 - UI コンポーネント・アイコン: 3:1 以上 原則: - 色だけで情報を伝えない(形、テキスト、パターンも使う) - リンクは色だけでなく下線でも区別 - グラフは色以外のパターンも使用 - ダークモード時もコントラスト比を確認
動的コンテンツ
ライブリージョン
code
aria-live の使い分け:
- "polite": ユーザーの操作を中断しない(推奨)
→ トースト通知、検索結果の更新
- "assertive": 即座に通知(緊急時のみ)
→ エラーメッセージ、セッション期限切れ
aria-atomic:
- "true": 領域全体を読み上げ
- "false": 変更部分のみ読み上げ(デフォルト)
SPA のページ遷移
code
- ページ遷移時にページタイトルを更新 - 新しいコンテンツにフォーカスを移動(または通知) - ローディング状態を aria-busy="true" で伝える - 読み込み完了を通知(aria-live 領域で)
アクセシビリティテスト
自動テスト
code
最低限のチェック: - HTML バリデーション - ランドマーク構造 - alt テキストの存在 - ラベルの関連付け - コントラスト比 - ARIA 属性の正しい使用
手動テスト
code
キーボードテスト: 1. Tab キーですべての操作可能な要素に到達できるか 2. フォーカスインジケーターが見えるか 3. Enter/Space でボタン/リンクが動作するか 4. Escape でモーダルが閉じるか スクリーンリーダーテスト: 1. 見出し構造でナビゲーションできるか 2. フォームのラベルが読み上げられるか 3. エラーメッセージが通知されるか 4. 動的コンテンツの更新が伝わるか
詳細: references/wcag-checklist.md
レビューチェックリスト
- • すべての画像に適切な alt テキストがある
- • 見出し階層が正しい(h1 → h2 → h3)
- • すべてのフォーム入力にラベルがある
- • キーボードのみで操作可能
- • フォーカスインジケーターが表示される
- • カラーコントラスト比が AA 基準を満たす
- • 色だけで情報を伝えていない
- • 動的コンテンツが支援技術に通知される
- • ランドマーク(header, nav, main, footer)が適切
リファレンス
- •references/wcag-checklist.md - WCAG 2.1 チェックリスト詳細
- •references/aria-patterns.md - ARIA パターン詳細