フロントエンドアクセシビリティ は何をしますか?
アクセシビリティはすべてのUI変更の一部です。設計、構築、テストの各段階で考慮されます。UIタスクは、キーボードのみで操作でき、すべてのコントロールが名前、役割、状態を通知し、自動チェックに合格し、テストが役割でクエリされるまで、完了したとは見なされません。
目標: WCAG 2.2 レベル AA — EUでは、European Accessibility Act(BFSG、EN 301 549などの国内法)により、多くの製品で必須となっています。発見事項は、WCAGのA/AA基準、または支援技術ユーザーが完了できない具体的なタスクを引用します。AAA基準と慣例(<h1>が1つ、44 pxのターゲットなど)は推奨事項であり、ブロッカーではありません。
| タスク | 参照先 |
|---|---|
| 要素、ランドマーク、見出し、ARIA、アクセシブルな名前、無効状態の選択 | references/semantics-and-aria.md |
| フォーカスリング、タブ順序、スキップリンク、ダイアログ、ルート変更、ウィジェットキーマップ | references/focus-and-keyboard.md |
| ラベル、オートコンプリート、入力タイプ、バリデーションエラー、送信動作 | references/forms.md |
| 変更の通知、ライブリージョン、トースト、代替テキスト、SVG、メディア | references/screen-readers.md |
| コントラスト、色、ターゲットサイズ、モーション、ズーム、リフロー、コンテンツ処理 | references/visual-and-motion.md |
| 自動および手動テスト、CI | references/testing.md |
| 既存UIの監査/レビュー、レポート形式 | references/audit.md |
| WCAG 2.2基準の検索 | references/wcag.md |
常に守るべきコアルール
ネイティブ要素を優先。 アクションには<button>、ナビゲーションには<a href> / ルーターの<Link>、<label>、<fieldset>、<table>、<dialog>、ランドマークを使用します。<div onClick>は絶対に使わないでください。ARIAがないことは、悪いARIAより優れています。役割は完全なキーボードモデルを約束します。複雑なウィジェット(コンボボックス、メニュー、日付ピッカー)は、プロジェクトのアクセシブルなヘッドレスライブラリから提供され、手作りはしません。
すべてのインタラクティブ要素にはアクセシブルな名前が必要です [4.1.2]。アイコンのみのボタンにはaria-labelを、アイコンにはaria-hidden="true"を設定します。表示ラベルのテキストは、アクセシブルな名前に含まれます [2.5.3]。リンクはどこに移動するかを示します。「こちらをクリック」は禁止です [2.4.4]。
キーボード [2.1.1, 2.1.2]。ポインターで動作するものはすべて、キーボードでも動作します。トラップは禁止です。タブ順序 = 視覚的順序。正のtabIndexは絶対に使用しません。Escapeキーは最前面のオーバーレイを閉じます。ドラッグとジェスチャーには、シングルポインターの代替手段が必要です [2.5.7, 2.5.1]。
可視フォーカス [2.4.7, 1.4.11]。:focus-visibleをスタイルします。確認済みの代替手段(隣接するすべての色に対して3:1以上)なしでoutline: noneを指定しないでください。フォーカスがスティッキーヘッダー/バナーの後ろに隠れないようにします [2.4.11] — scroll-padding-topを使用します。
フォーカス管理。 ダイアログ: 開くときにフォーカスが内部に移動し、トラップされ、背景はinertになり、閉じるとトリガーに戻ります。SPAルート変更: document.titleを更新し [2.4.2]、新しい<h1>(tabIndex={-1})または<main>にフォーカスを移動します。
フォーム [1.3.1, 3.3.1, 3.3.2]。すべてのコントロールに表示可能な<label>を配置します。プレースホルダーはラベルではありません。正しいtype、inputMode、autoCompleteを使用します [1.3.5]。エラーはインラインで表示し、aria-describedbyでリンクし、フィールドにはaria-invalid="true"を設定し、送信時には最初の無効なフィールドにフォーカスを移動します。送信時にバリデーションを行います。有効になるまで送信ボタンを無効にしないでください。ペーストをブロックしないでください [3.3.8]。
動的な変更を通知する [4.1.3]。フィールド固有の変更 → aria-describedby。緊急でない変更(保存済み、結果数、読み込み中) → role="status"。緊急のフォームレベルのエラー → role="alert"。ライブリージョンは、テキストが変更される前にDOMに存在している必要があります。
色とコントラスト [1.4.3, 1.4.11, 1.4.1]。テキストは4.5:1以上(大きいテキストは3:1以上)、UIの境界線、アイコン、フォーカスリングは3:1以上 — デザイントークンで強制します。色だけを唯一の手がかりにしてはいけません。
ターゲット [2.5.8]。24×24 CSS px以上、または十分な間隔。デスクトップでは40 px、タッチでは44 pxを目指します。装飾的なオーバーレイにはpointer-events: noneを設定します。
モーションと時間 [2.3.3, 2.2.2]。アニメーションは@media (prefers-reduced-motion: no-preference)を介してオプトインします。パララックス/自動再生は、モーション軽減設定が有効な場合はオフにします。5秒以上動くものは一時停止できる必要があります。アクションやエラーがあるトーストは、ユーザーが閉じるまで表示されたままにします。
ズームとリフロー [1.4.4, 1.4.10]。テキストサイズ200%、幅320 CSS pxで、水平スクロールなしで動作します。maximum-scale=1 / user-scalable=noは絶対に使用しないでください。
ページの基本。 <html lang>が設定され、UIの言語で更新されます [3.1.1]。表示可能な<main>が1つ。見出しはアウトラインを形成します。ナビゲーションが<main>の前にある場合、スキップリンクが最初にあります [2.4.1]。
画像。 意味がある場合 → altは目的を説明します。装飾的な場合 → alt=""。機能的な場合(画像がリンク/ボタンである場合) → アクションを説明します [1.1.1]。
テストの義務
すべてのUI変更には以下が含まれます。
- 役割と名前でクエリする(
getByRole)コンポーネントテスト、およびキーボードパスをカバーするテスト(user.tab()、{Escape}、toHaveFocus())、 - addon-a11yチェックがエラーとして実行されるStorybookストーリー(CIで失敗)、
- 重要なページと状態でPlaywright +
@axe-core/playwrightスキャン(WCAG 2.x A/AAタグ)、 - フローの手動キーボードのみの通過、重要なフローではスクリーンリーダー(VoiceOver/NVDA)の通過。
自動ツールは問題の一部しか見つけられません。axeの実行がクリーンでもWCAG準拠とは限りません。詳細: references/testing.md。
完了前に変更をスキャンする
| パターン | 修正 |
|---|---|
<div onClick / <span onClick | <button>、またはナビゲーションする場合は<a href> |
キーハンドリングのないrole="button"/role="tab" | ネイティブ要素またはAPGキーマップ |
focus-visibleの代替なしのoutline: none / outline-none | ブラウザリングを維持するか、確認済みのカスタムリングを使用 |
正のtabIndex | DOMの順序を修正し、0 / -1を使用 |
altなしの<img | alt=""または目的の説明 |
| 名前なしのアイコンボタン | aria-label、アイコンはaria-hidden |
<label>なし/プレースホルダーをラベルとして使用する入力 | 表示可能なリンクされたラベル |
送信ボタンのdisabled={!isValid} | 有効に保ち、送信時に検証 |
{msg && <div role="status">…} | 最初に空のリージョンをレンダリングし、そのテキストを更新 |
成功メッセージでのaria-live="assertive" | role="status" |
フォーカス可能な要素の上または上にあるaria-hidden | 削除するか、サブツリーをinertにする |
onPaste + preventDefault | ペーストを許可 |
maximum-scale=1 / user-scalable=no | 削除 |
scroll-padding-topなしのスティッキーヘッダー | スクローラーにパディングを追加 |
| ボタン代替なしのドラッグ/ジェスチャー | シングルポインターパスを追加 |
transition: all、モーション軽減ガードなしのモーション | プロパティをリストし、no-preferenceでラップ |
報告
監査とレビューは会話の言語で報告し、根本原因ごとに1つの発見事項として、すべての場所、WCAG基準、ユーザーへの影響、具体的な修正を含めます。形式はreferences/audit.mdにあります。深刻度はコードレビュースキルにマッピングされます。HIGH → Blocker/Major、MEDIUM → Major/Minor、LOW → Minor。
出典
以下から組み合わせて作成: Addy Osmani氏のweb-quality-skills accessibility (MIT)、Jakub Krehel氏のbetter-accessibility (MIT)、ibelick氏のfixing-accessibility (MIT)、VercelのWeb Interface Guidelines (MIT);W3C WCAG 2.2 および WAI-ARIA Authoring Practices。