awesome-accessibility-audit について
UIやマークアップをWCAGに照らして確認し、具体的な修正案を報告する読み取り専用スキルです。ページ、コンポーネント、フォーム、操作フローをレビューするチーム向けで、指摘には場所、影響、重大度、修正案が含まれます。
主な機能
- 01セマンティックHTMLと構造の確認
- 02キーボード操作とフォーカスの確認
- 03ラベル、名前、色、コントラストの確認
- 04動的コンテンツとメディアの確認
- 05WCAG 2.2基準の確認
- 06具体的な修正案と重大度の提示
活用シーン
- 01リリース前のページレビュー
- 02フォーム、ダイアログ、操作コンポーネントの監査
- 03UI変更後のアクセシビリティ確認
- 04コンポーネント担当者向けの指摘整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ khasky/ awesome-agent-skills --skill awesome-accessibility-auditインストール後、Claude Code で/awesome-accessibility-auditを入力して読み込まれたか確認します。
同梱ファイルevals/eval_queries.json
詳細
アクセシビリティ監査
UI とマークアップを確認し、各指摘に対して WCAG に沿った具体的な修正方法を提示して、すべてのユーザーがインターフェースを認識、操作、理解できるようにします。
読み取り専用です。指摘事項と、それぞれを解決するマークアップまたは属性の変更を報告しますが、変更は適用しません。レポート内のコードスニペットは、満たす基準と並べて確認できます。同じ編集を黙って適用するのは適切ではありません。レポートをコンポーネントの担当者に渡してください。
いつ実行するか
- ユーザーが「アクセシビリティ」、「a11y」、「WCAG」、または「スクリーンリーダーのサポート」について尋ねたとき
- 新しいページやコンポーネントをリリースする前
- フォーム、モーダル、またはインタラクティブな UI をレビューするとき
- インタラクションやコンテンツに影響するデザインまたは UI の変更後
作業プロセス
- 対象範囲を定義する — レビューするページ、コンポーネント、またはフローを指定します(例:ログインフォーム、レポートテーブル、モーダルダイアログ)。
- 各領域を確認する — セマンティック HTML、キーボード操作、ラベルと名前、色とコントラスト、動的コンテンツ、モーションを確認します。以下のチェックリストを使用してください。
- 指摘事項を記録する — 場所(コンポーネント/ファイルまたは要素の種類)、WCAG の基準または原則、問題、影響、推奨する修正を記載します。重大度は「Critical/High/Medium」で示します。
- 修正方法を提示し、適用はしない — 可能であれば、レポートにコードスニペットまたは属性の変更を記載します。ネイティブ HTML と適切な ARIA で十分な場合は、カスタムウィジェットよりもそれらを優先してください。
- フォローアップを推奨する — 自動化ツール(例:axe、Lighthouse、pa11y。CI では重大な違反があればビルドを失敗させる)と、より広範なカバレッジを得るための手動テストを提案します。自動化ツールで検出できる WCAG の問題はおよそ 30~40%で、残りは手動での確認が必要です。フロー × 支援技術のマトリックスを推奨します。各主要ユーザーフローを、キーボードのみ、スクリーンリーダー(Mac/iOS の VoiceOver、Windows の NVDA、Android の TalkBack)、200%および 400%のズーム/リフロー(WCAG 1.4.10)、Windows ハイコントラスト、モーションの軽減でテストしてください。該当する場合は、Voice Control/Dragon と Switch Control も記録します。単一のレビューだけで WCAG に完全準拠していると主張しないでください。
- テストでの自動アサーションには、
axe-coreの.withTags(['wcag2a','wcag2aa'])を使用すると、特定の WCAG レベルを対象にでき、違反があれば CI を失敗させられます。Playwright のpage.ariaSnapshot()(1.59 以降)では、ダイアログ、メニュー、複合ウィジェットのアクセシビリティツリーをアサートできます。これは axe/Lighthouse では得られない範囲をカバーします。 - 自動スキャンは複数のビューポート(デフォルトだけでなく、モバイルとデスクトップのブレークポイント)で実行してください。フォーカスの遮蔽、ターゲットの重なり、リフロー違反はビューポートサイズによって現れたり消えたりするため、単一ビューポートのスキャンでは検出漏れが生じます。
- テストでの自動アサーションには、
完了条件:対象範囲が明記され、以下の各チェックリスト領域が確認され、各指摘に場所、WCAG の基準、修正方法が記載されていること。また、スクリーンリーダーまたは別のビューポートでしか判断できない項目は、未確認として明記し、確認済みと見なさないこと。
確認領域とチェックリスト
1. セマンティック HTML と構造
- 各ページの
<h1>は1つにし、見出しレベルを順番に使用します(2 → 4のように飛ばさない)。 - メインコンテンツへのスキップリンクを、最初にフォーカス可能な要素として配置します(WCAG 2.4.1 ブロックスキップ)。
- ビューポートのメタデータでズームを無効にしません。
user-scalable=noとmaximum-scale=1が指定されていないか確認します(WCAG 1.4.4)。 - すべてのページに、トピックや目的を説明する
<title>を設定し、SPAのルート変更時にタイトルも変更します(2.4.2 ページタイトル、A)。 -
<html>のlang属性でページの言語を設定します(3.1.1、A)。別の言語の文章には、その文章自体にlangを指定します(3.1.2 部分の言語、AA)。 - 画面の向きが不可欠でない限り、コンテンツを一つの向きに固定しません(CSSまたはマニフェストによる画面の向きの固定)(1.3.4 画面の向き、AA)。
- リフロー:幅320 CSS px(幅1280pxのビューポートを400%に拡大)では、データテーブル、地図など、二次元スクロールが必要なコンテンツを除き、コンテンツを二次元にスクロールする必要がないようにします(1.4.10、AA)。
- テキスト間隔:行の高さを1.5、段落間隔を2倍、文字間隔を0.12em、単語間隔を0.16emに設定しても、テキストが切れたり、重なったり、消えたりしないようにします。固定の高さを持つテキストコンテナーや、テキストに対する
overflow: hiddenを確認します(1.4.12、AA)。 - 適切な場所にランドマークとして
<main>、<nav>、<aside>、<footer>を使用します。 - リストには
<ul>/<ol>/<li>を使用します。表には該当する場合、<th>、scope、キャプションを使用します。 - ボタンには
<button>または<input type="submit">を、リンクには<a href="...">を使用します。ロール、キーボード操作、フォーカスを実装せずに、操作に<div onclick>を使用しないでください。 - フォームコントロールには適切な型とグループ化(グループには
<fieldset>と<legend>)を設定します。
2. キーボード
- すべてのインタラクティブな要素をフォーカス可能にします(モーダル用に管理する場合を除き、ボタンやリンクに
tabindex="-1"を設定しないでください)。 - フォーカス順序を論理的にします(視覚的な順序に合わせるか、明示的に管理します)。
- フォーカスインジケーターを視認できるようにします(アウトラインまたはカスタムスタイル)。代替を用意せずに
outline: noneで削除しないでください。:focus-visible(マウスクリック時にリングを表示しない)と、複合コントロール向けの:focus-withinを推奨します。 - キーボードトラップをなくします。ユーザーがモーダルやメニューからTabキーで移動できるようにし、想定される場合はEscapeキーで閉じられるようにします。
- カスタムウィジェット(タブ、アコーディオン、メニュー)をキーボードで操作できるようにします(Enter/Spaceで有効化し、該当する場合は矢印キーも使用します)。
- ホバーまたはフォーカス時に表示されるコンテンツ(ツールチップ、ポップオーバー、サブメニュー)は、ポインターを移動せずに閉じることができ(Escape)、ポインターを移動しても消えず(ポインターを重ねられる)、閉じるか無関係になるまで表示され続けるようにします(1.4.13、AA)。ホバーだけで利用できる機能には、キーボードとタッチで操作する方法も用意します。
3. ラベルと名前
- すべてのフォーム入力に、視認できる
<label>またはaria-labelを設定し、ラベルを関連付けます(例:for/idまたはラベルで囲みます)。 - 入力には適切な
type/inputmodeとautocomplete属性を設定します(WCAG 1.3.5 入力目的の特定)。 - フォームエラーは該当するフィールドの横にインラインで表示し、
aria-describedbyを使って各エラーをそのフィールドに関連付けます(設定しないと、フィールドにフォーカスしたときにスクリーンリーダーがエラーを読み上げません)。送信時は最初のエラーにフォーカスを移動します。長いフォームでは、キーボードでフォーカス可能なエラーの概要を先頭に追加し、エラーのある各フィールドへのリンクを設けます(GOV.UKのパターン)。 - 送信時にエラーが発生しても、ユーザーの入力を消去せず保持します(再入力の負担を軽減します。3.3.7を参照)。入力のたびではなく、フォーカスが外れたときに検証します。
- パスワードフィールドに限らず、どこでも貼り付けをブロックしないでください(
onPasteとpreventDefaultの組み合わせはアンチパターンです)。 - ボタンとリンクには、明確で一意な名前(テキストコンテンツまたは
aria-label)を設定します。文脈なしで「ここをクリック」や「続きを読む」を使用しないでください。 - 名前とラベルの一致:音声コントロールのユーザーが表示されている名前を読み上げて操作できるよう、コントロールのアクセシブル名に表示テキストを含め、できればそのテキストから始めます(2.5.3、A)。表示テキストを異なる語句で置き換える
aria-labelは不適合です。 - 画像:意味のある画像には内容を説明する
altを設定し、装飾画像にはalt=""またはrole="presentation"を設定します。装飾アイコン(インラインSVG、アイコンフォント)にはaria-hidden="true"を設定します。 - iframeと埋め込みコンテンツには
titleまたはaria-labelを設定します。
4. 色とコントラスト
- テキストのコントラスト比が基準を満たしている(例:通常のテキストは4.5:1、大きなテキストは3:1、UIコンポーネントは3:1)。背景色とのコントラストを確認してください。(新しいデザインシステムでは、WCAG 3.0で採用が予定されている知覚モデルのAPCAを使用する場合があります。プロジェクトがAPCAを対象としている場合はその旨を記載し、特に指示がない限り、WCAG 2.2の比率に照らして監査してください。)
- 情報を色だけで伝えていない(例:必須項目、エラー、ステータス)。アイコン、テキスト、パターンも併用してください。
- フォーカスインジケーターが見え、色の変化だけに依存していない。
5. 動的コンテンツとフォーカス
- 表示または更新されるコンテンツ(例:トースト、ライブ検索結果)が読み上げられる。
aria-live="assertive"は、緊急の割り込み(エラー、対応が必要なトースト)にのみ使用し、aria-live="polite"はフィードの更新や結果件数に使用してください。 - SPAのルート変更がスクリーンリーダーに通知されず、新しいページを
aria-live="polite"領域で通知するか、新しいページの<h1>にフォーカスを移動する。 - モーダルとダイアログ:開いたときにフォーカスをモーダル内に移動し、内部に留め、閉じたときに起動元に戻します。パターンに応じて、最初のフォーカス可能な要素または明示的な
autoFocusを使用してください。 - 状態を伝える:展開/折りたたみ(
aria-expanded)、選択状態(aria-selected)、現在の項目(aria-current)、無効状態(disabledまたはaria-disabled)。
6. モーション、メディア、時間
- アニメーションが
prefers-reduced-motionに対応している(動きを軽減または無効化する)。これに対応していないモーションは指摘してください(2.3.3 インタラクションによるアニメーション、AAA — 中程度として報告)。 - 1秒間に3回を超えて点滅するものがない(2.3.1 3回の閾値以下の点滅、A)。アニメーションGIF、動画、キャンバスエフェクトを確認してください。
- 他のコンテンツと並行して5秒を超えて自動的に動く、点滅する、またはスクロールするもの(カルーセル、ティッカー、自動再生の背景動画など)には、一時停止、停止、または非表示にするコントロールがある。自動更新コンテンツにも同様のコントロールが必要です(2.2.2、A)。
- 3秒を超えて自動再生される音声を一時停止または停止できるか、システム音量とは個別に音量を調整できる(1.4.2、A)。
- 音声付きの収録済み動画には字幕(1.2.2、A)があり、視覚情報のみの内容には音声解説またはテキストによる代替手段がある(1.2.3、A、1.2.5 音声解説、AA)。音声付きのライブ動画には字幕がある(1.2.4、AA)。音声のみおよび映像のみのメディアには、文字起こしまたは同等のものがある(1.2.1、A)。プレーヤーのコントロール自体がキーボードで操作でき、ラベル付けされていることも確認してください。
7. WCAG 2.2の追加項目(見落とされがち)
- 2.4.11 フォーカスが隠れない — 固定ヘッダー/フッターがフォーカス中の要素を隠してはいけません(
scroll-margin-topが役立ちます)。 - 2.5.8 ターゲットサイズ — インタラクティブなターゲットは24×24 CSS px以上にするか、それより小さいターゲット同士に十分な間隔を設けます。表示されるコントロールが小さい場合は、疑似要素でヒット領域を40~44pxまで広げます。2つのインタラクティブ要素のヒット領域が重なってはいけません。チェックボックス/ラジオボタンとそのラベルは、ひと続きのターゲットを共有します。
- 2.5.7 ドラッグ操作 — すべてのドラッグ操作に、クリック/タップによる代替手段がある。
- 3.3.7 冗長な入力 — 1つのフロー内で同じ情報を2回入力させない。
- 3.3.8 アクセシブルな認証 — ログインに認知テストを求めない。パスワード欄への貼り付けを許可し、パスキーまたはメールリンクによる代替手段を提供する。
- 3.2.6 一貫したヘルプ — すべてのページで、ヘルプの仕組みを同じ場所に表示する。
出力
各問題について:
**[Location: file or component/element]**
- **Issue:** [What is wrong.]
- **WCAG / principle:** [Criterion or principle, e.g. 1.3.1 Info and Relationships, 2.1.1 Keyboard.]
- **Impact:** [Who is affected and how.]
- **Recommendation:** [Concrete fix: code or attribute. For contrast findings, cite computed ratios: "#aaa on #fff = 2.32:1, needs 4.5:1 → use #595959 (7.0:1)".]
- **Severity:** Critical | High | Medium
記入例:
**[src/components/LoginForm.tsx — error message]**
- **Issue:** The "Invalid email" error renders visually below the field but is not associated with the input and is never announced.
- **WCAG / principle:** 3.3.1 Error Identification; 4.1.3 Status Messages.
- **Impact:** A screen-reader user submits, hears nothing, and cannot tell the form failed or which field to fix.
- **Recommendation:** Link it: `<input aria-describedby="email-err" aria-invalid="true">` + `<p id="email-err" role="alert">Invalid email</p>`; on submit, move focus to the first invalid field.
- **Severity:** Critical
概要:"確認済み:[対象範囲]。重大な問題X件、高リスクY件、中程度の問題Z件を確認しました。自動スキャン(axe/Lighthouse)とキーボード/スクリーンリーダーによるテストを推奨します。"
重大度
- 重大 — 中核的なタスクを妨げる(例:フォームを送信できない、キーボードで操作できない、必須項目にラベルがない)。リリース前に修正してください。
- 高 — 大きな障壁となる(例:コントラストが不十分、見出しがない、順序が分かりにくい)。早急に修正してください。
- 中程度 — 改善点(例:ラベルの重複、軽微なコントラストの問題)。バックログに追加するか、コンポーネントを変更する際に修正してください。
良い例と悪い例
ボタン:
<div onclick="submit()">Submit</div>
<button type="submit">Submit</button>
画像:
<img src="decoration.svg" alt="" role="presentation">
<img src="chart.png" alt="Bar chart showing revenue up 20% in Q4">
フォーム:
<input type="email" placeholder="Email">
<label for="email">Email</label>
<input id="email" type="email" placeholder="[email protected]">
ルールに例外が生じる場合
各チェック項目には、最もよくある失敗を防ぐためのデフォルトが定められています。状況によって失敗の形が逆転する場合は、ルールも逆になることがあります。たとえば、スクリーンリーダーで読み飛ばすべき装飾要素にはラベルではなく aria-hidden が必要です。また、ネイティブの <button> に keydown ハンドラーを追加してはいけません(アクティベーションが二重に発生します)。必要なのは、例外を暗記することではなく、逆転を見抜くことです。例外によって、正しさとアクセシビリティの最低基準を損なってはいけません。キーボードで操作できること、プログラムによる名前があること、十分なコントラストがあることは譲れません。
ルール
- 完全に準拠していると主張しないでください。「レビューした範囲で見つかった問題」と表現してください。網羅的な確認のため、自動テストと手動テストを推奨してください。
- ネイティブ HTML を優先してください。
<button>、<label>、<main>などを使用してください。HTML では表現できないセマンティクスには ARIA を使用してください(例:カスタムアコーディオンのaria-expanded)。 - コンポーネントライブラリ — プロジェクトでライブラリ(Radix、MUI など)が使用されている場合は、ライブラリのアクセシビリティパターン(フォーカストラップ、ロールなど)に触れ、再実装するのではなく、正しく使用されていることを確認してください。
チェックリスト(完了前)
- 対象範囲が明確に定義されている
- 各指摘に、場所、問題、WCAG 参照、推奨事項、重大度が含まれている
- セマンティックな構造、キーボード操作、ラベル/名前を少なくとも確認している
- 追加の確認として(自動テストと手動テスト)を提案している
- 完全な監査なしに「WCAG 2.2 に完全準拠」と主張していない
アンチパターン
| アンチパターン | より良い方法 |
|---|---|
| 色のコントラストだけを確認する | キーボード操作、ラベル、構造、動的コンテンツも確認する |
| あらゆる場所で「aria-label を追加する」と提案する | 可視ラベルとセマンティック HTML を優先し、必要な場合に ARIA を使用する |
| モーダル内のフォーカス順序を無視する | フォーカストラップとフォーカスを戻す動作を記録する |
| コードレビューだけで準拠していると主張する | axe/Lighthouse と実際の支援技術を使ったテストを推奨する |