better-accessibility について
better-accessibilityは、インターフェースのアクセシビリティをレビューし修正するスキルです。開発者やレビュー担当者向けに、セマンティクス、キーボード操作、スクリーンリーダー、フォーム、モーション、ズームを扱い、指摘をWCAG 2.2のAまたはAA基準に結び付けます。
主な機能
- 01セマンティクスとアクセシブルネームの確認
- 02キーボード操作と可視フォーカスの検査
- 03フォームラベルとエラー通知の監査
- 04モーション設定とズームへの対応
- 05WCAG基準に沿った指摘
活用シーン
- 01キーボードだけで画面フローを完了できるか確認
- 02スクリーンリーダーの名前、役割、状態を検査
- 03フォームのラベルと検証の問題を発見
- 04動きを減らす設定とズーム時の挙動を評価
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jakubkrehel/ skills --skill better-accessibilityインストール後、Claude Code で/better-accessibilityを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
focus-and-keyboard.mdforms.mdhit-areas.mdmotion-and-zoom.mdscreen-readers.mdsemantics-and-aria.mdagents/openai.yaml詳細
アクセシビリティ
このスキルでは、セマンティクス、キーボード操作とフォーカスの挙動、アクセシブルネーム、フォーム、通知、モーション、ズームをレビューし、修正します。各問題について、該当する WCAG 基準を示し、プロジェクトのスタイリングシステムに沿って修正します。
レビューでは、2通りの確認を行います。まず、マウスを使わずにすべての操作を完了できるか、キーボードのみで確認します。次に、すべてのコントロールで名前、ロール、状態が読み上げられるか、スクリーンリーダーで確認します。判断に迷ったら、独自の再構築ではなくプラットフォームのデフォルトを選び、ARIA は追加するより削除してください。
コントラストの測定と色の修正は better-colors の担当です。テキストサイズ、iOS の入力ズーム、言語メタデータは better-typography の担当です。ターゲット間の間隔と空間的な RTL は better-layout の担当です。ラベル、エラー、代替テキストの文言は better-writing の担当です。アニメーションのレシピ、ホバーのスタイリング、スクロールの封じ込めは better-ui の担当です。
慣例ではなく基準
指摘事項には、違反する WCAG 2.2 レベル A または AA の基準番号、あるいは支援技術を使うユーザーが完了できない具体的なタスクを記載します。それ以外はすべて推奨事項であり、HIGH にはしません。これには、AAA の基準、APG の慣例、<h1> を1つにすることや見出しレベルを飛ばさないこと、ターゲットを44pxまたは40pxにすることが含まれます。以下の基準値は厳密な値です。大きめのターゲットは経験則なので、使いやすさが保たれている既存の密度は維持してください。
まずネイティブ要素を使う
ARIA の第一原則は、ネイティブ要素がある場合は ARIA を使わないことです。アクションには <button>、ナビゲーションには <a href> を使い、<div onClick> は決して使いません。本物のリンクは Cmd/Ctrl キーや中クリックに対応する必要があります。ランドマークとボタン対リンクの使い分けについては、semantics-and-aria.md を参照してください。
無効とは利用できないこと
コントロールが本当に利用できない場合は、ネイティブの disabled を使ってください。フォーカス可能な状態を保つ必要がある場合に限り、aria-disabled="true" を使い、その場合はコードでポインター、キーボード、フォームの動作を無効にし、状態を明示的にスタイリングしてください。ルールについては semantics-and-aria.md を参照してください。
視認できるフォーカスリング
:focus だけではなく :focus-visible をスタイリングしてください。キーボードユーザーにはリングが表示され、マウスユーザーには通常表示されません。ブラウザーの変更されていないインジケーターを優先してください。
独自のリングには、プロジェクトのフォーカストークン、または明示的な別の色が必要です。1.4.11 に基づき、currentColor も含め、リングが接するすべての色に対して 3:1 のコントラストを確保する必要があります。コントラストに 3:1 の変化をつけた 2px の実線の輪郭は、2.4.13 の AAA 目標です。検証済みの代替手段なしに outline: none を使わないでください。また、強制カラーモードではシステムカラーを維持してください。
フォーカスされた要素が、固定ヘッダー、フッター、バナーの背後に完全に隠れてはなりません(2.4.11)。スクローラーに固定表示部分の高さ分のパディングを追加してください。この修正は better-layout の担当です。レシピについては focus-and-keyboard.md を参照してください。
完全なキーボードサポート
すべてのポインター操作には、キーボードで操作する方法が必要です。ARIA APG のパターンに従ってください。オーバーレイは Escape で閉じ、複合ウィジェット内では矢印キーで移動し、ウィジェット間は Tab で移動し、ボタンは Enter と Space で操作します。
自然なタブ順序に加える場合のみ tabindex="0" を使い、プログラムでフォーカスする場合は tabindex="-1" を使ってください。正の値を使うと順序が崩れます。複合ウィジェットではロービング tabindex を使い、アクティブな項目を 0、それ以外をすべて -1 にします。コンボボックスのようにフォーカスを入力欄に留める必要がある場合は、代わりに aria-activedescendant を使ってください。各ウィジェットのキー操作については focus-and-keyboard.md を参照してください。
フォーカスを閉じ込め、元に戻す
showModal() で開く <dialog> を優先してください。これにより背景が不活性になり、Escape キーにも対応します。独自のオーバーレイでは、背景に inert を設定し、オーバーレイ自体に role="dialog" と aria-modal="true" を設定します。いずれの場合も、開いたときは内部にフォーカスを移し、閉じたときは起動元に戻してください。
クライアントサイドのルート変更では、自動的に何もリセットされません。document.title を更新し、新しいビューの <h1> または <main> にフォーカスを移してください。どちらのレシピも focus-and-keyboard.md にあります。
最小ヒット領域
WCAG 2.5.8 のレベル AA の基準は、24×24 CSS ピクセルのターゲット、または例外のいずれかです。密度に余裕がある場合は、タッチでは 44×44px、デスクトップでは 40×40px を目指してください。表示要素を小さいままにする必要がある場合は、疑似要素で領域を拡張してください。
拡張したヒット領域を決して重ねないでください。装飾レイヤーには pointer-events: none を指定し、光彩が下にあるコントロールを操作するためのクリックを奪わないようにしてください。
ドラッグ操作にはすべて、同じ項目を並べ替えたり移動したりできるボタンやメニューなど、単一ポインターで操作できる代替手段が必要です(2.5.7)。サイズ、例外、衝突ルールについては、hit-areas.md を参照してください。
すべてのコントロールにラベルと型を設定する
すべての入力には、<label for> または入力を囲む <label> を設定してください。プレースホルダーはラベルの代わりにはなりません。ラベルとコントロールは同じヒットターゲットを共有し、チェックボックスとそのテキストの間に操作できない領域ができないようにしてください。
有効な autocomplete トークンと説明的な name 属性に加え、適切なキーボードを表示する type と inputmode を指定してください。貼り付けを決して禁止しないでください。ユーザーはパスワードやワンタイムコードを貼り付けます。forms.md を参照してください。
エラーを通知する
送信時に検証し、フォームが有効になるまで送信を無効にしないでください。エラーのあるフィールドには aria-invalid="true" を設定し、aria-describedby でインラインエラーテキストを参照させ、最初の無効なフィールドにフォーカスを移してください。リクエストの実行中の送信動作については、forms.md を参照してください。
あらゆる場所でアクセシブルな名前を付ける
アイコンのみのボタンには、説明的な aria-label が必要です。表示されているラベルテキストは、アクセシブルな名前にも含めてください。装飾要素には aria-hidden="true" を指定します。フォーカス可能な要素には決して指定しないでください。
色にもう一つの手掛かりを組み合わせる
ステータスには、色に加えてアイコン、テキスト、下線など、冗長な手掛かりが必要です(1.4.1)。
このスキルで、適用されるコントラスト要件を判断します。
| 基準 | 対象 | 最小値 |
|---|---|---|
| 1.4.3 AA | テキスト | 4.5:1 |
| 1.4.3 AA | 大きなテキスト、24px 以上または太字の 18.67px 以上 | 3:1 |
| 1.4.11 AA | UI コンポーネントの境界、状態、意味のあるグラフィック | 3:1 |
非アクティブなコントロールとロゴは対象外です。better-colors を使って、レンダリングされた色の組み合わせを測定してください。要件を満たさない場合は、色を変更せずに、色の組み合わせと満たしていない基準を報告してください。ただし、変更を求められた場合は除きます。
prefers-reduced-motion を尊重する
動きのある表現は @media (prefers-reduced-motion: no-preference) で囲み、オプトインにしてください。視差効果と自動再生は完全に停止し、スライドや拡大・縮小は、動きを抑える設定時には不透明度のクロスフェードに置き換えてください。motion-and-zoom.md を参照してください。
ユーザーが必要とするものをタイマーで消さない
5 秒を超えて自動的に動く、点滅する、または更新されるものには、視認できる一時停止コントロールが必要です(2.2.2)。アクションまたはエラーを含むトーストは、閉じられるまで表示し続けてください。ルールについては、motion-and-zoom.md を参照してください。
動的コンテンツを通知する
3 つの仕組みには、それぞれ異なる役割があります。aria-describedby はフィールド固有の検証結果を伝えます。丁寧なライブリージョン(role="status")は、トーストや結果件数など、コントロールに関連付けられていない緊急性の低い更新を伝えます。role="alert" は、コントロールに関連付けられていない緊急のエラーだけを伝えます。
丁寧な通知を繰り返す場合は、テキストを更新する前に、空の状態で安定したライブリージョンをレンダリングしておく必要があります。動的に挿入されるアラートへの対応状況はさまざまなので、対象とするスクリーンリーダーでテストしてください。screen-readers.md を参照してください。
目的に応じた代替テキスト
装飾画像には alt="" を指定してください。情報を伝える画像には、その意味を説明してください。機能を持つ画像には、画像そのものではなくアクションを説明してください。完全な表は screen-readers.md にあります。
構造をナビゲーションに活用する
各セクションの内容を表し、一貫したアウトラインを構成する見出しを使用してください。表示される主要な <main> ランドマークを 1 つ設けてください。繰り返し表示されるナビゲーションやクロームがその前にある場合は、「コンテンツへスキップ」リンクを最初にフォーカス可能な要素にしてください。アンカーのある見出しには scroll-margin-block-start を設定してください。
ズームとテキストサイズ変更に耐える
テキストは200%に拡大しても表示され(1.4.4)、ページは幅320pxで横スクロールなしにリフローする必要があります(1.4.10)。テキストコンテナーには height ではなく min-height を指定し、残りの修正は better-layout が担当します。viewport meta に maximum-scale=1 や user-scalable=no を設定しないでください。iOS の入力時ズームは、代わりに better-typography の 16px ルールで修正します。
完了前の確認事項
| パターン | 修正 |
|---|---|
近くに focus-visible による置き換えがない outline: none または outline-none | ブラウザーのフォーカスリングを復元するか、検証済みのカスタムフォーカスリングを追加します |
<div onClick または <span onClick | <button> を使用します。遷移する場合は <a href> を使用します |
onKeyDown がない role="button" または role="tab" | ネイティブ要素を使用するか、APG のキー操作を実装します |
tabIndex={1} または正の値を持つ tabindex | DOM の順序を修正し、0 を使用します |
送信ボタンの disabled={!isValid} | 有効な状態を維持し、送信時に検証します |
{msg && <div role="status"> のように、テキストとともに領域をマウントする | 先に空の領域をレンダリングし、そのテキストを更新します |
成功通知の aria-live="assertive" | role="status" |
alt 属性のない <img | 装飾目的なら alt=""、それ以外なら目的を説明します |
表示ラベルのテキストを含まない aria-label | 名前の先頭に表示テキストを含めます |
ボタン、リンク、入力要素の祖先にある aria-hidden | 削除するか、サブツリーを inert にします |
maximum-scale=1 または user-scalable=no | 削除します |
ネイティブの disabled コントロールに付いたツールチップ | 横にテキストを表示するか、フォーカス可能な状態を保つため aria-disabled を使用します |
ボタンによる代替手段がない onDragStart またはドラッグライブラリ | 同じ結果を得られる、単一ポインターによる操作経路を追加します |
報告
重大度。 HIGH はタスクを妨げる、支援技術からコンテンツを隠す、またはシステム上の障害を引き起こす問題です。MEDIUM は操作を著しく困難にする問題です。LOW は局所的な仕上げの問題です。この領域は、better-interface のエスカレーショントリガーに該当すると一目で判断できるものが HIGH です。該当するのは、アクセシブルな名前の欠落、フォーカスインジケーターの欠落、キーボード操作経路のないポインター操作経路です。また、動きの抑制設定を無視すること、幅320pxまたは200%拡大時にコンテンツが失われること、色だけで意味を伝えることも該当します。
検証。 ブラウザーを使わずに確認する場合は、すべてのインタラクティブ要素のアクセシブルな名前、ネイティブでないコントロールのキーボードハンドラー、フォーカススタイル、prefers-reduced-motion のガード、入力要素に関連付けられたフォームラベルを確認します。ブラウザーを使う場合は、操作フローを順番に Tab キーで移動し、アクセシビリティツリーから計算済みの名前とロールを読み取り、各停止位置でフォーカスインジケーターが表示されることを確認し、自動監査を実行します。実行できなかった確認項目はすべて Not verified と報告します。
形式。 該当する原則ごとに、重大度の高い順に指摘事項をまとめます。根本原因ごとに1行とし、発生しているすべての場所を記載します。
| 重大度 | 場所 | 修正前 | 修正後 | 理由 |
|---|
Location は path/to/file:line 形式です。Why には該当する WCAG の基準または原則と、ユーザーへの影響を記載します。
HIGH が残っている場合は最後に Block、それ以外は Approve と記載し、残りの作業は表に記載します。確認していない範囲について、決して Approve としてはいけません。報告事項がない場合は "No actionable accessibility findings" と記載し、検証結果も報告します。