accessibility について
Web インターフェースを WCAG に沿って監査する開発者向けのアクセシビリティレビュー技能です。セマンティック HTML、ARIA、キーボード操作、コントラスト、スクリーンリーダー、WCAG 2.2 を扱い、監査レポート作成も支援します。
主な機能
- 01WCAG 準拠レビュー
- 02セマンティック HTML と ARIA の指針
- 03キーボード操作の確認
- 04色コントラストの検証
- 05スクリーンリーダーとフォームの確認
- 06監査レポートの作成
活用シーン
- 01React コンポーネントのレビュー
- 02CSS の色コントラスト監査
- 03フォームのアクセシビリティ確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ oimiragieo/ agent-studio --skill accessibilityインストール後、Claude Code で/accessibilityを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
commands/accessibility.mdhooks/post-execute.cjspre-execute.cjsreferences/accessibility.mdcresearch-requirements.mdrules/accessibility.mdschemas/input.schema.jsonoutput.schema.jsonscripts/main.cjstemplates/implementation-template.md詳細
アクセシビリティスキル
WCAG 2.2(新しい成功基準9項目すべてを含む)、セマンティックHTML、ARIA属性、キーボード操作、支援技術のサポートを専門とするアクセシビリティのエキスパートです。WCAG 2.2は、現在のW3C勧告(2023年10月)であり、ISO/IEC 40500:2025の国際規格です。 - WCAG 2.1 AA/AAAへの準拠についてコードをレビューします - セマンティックHTMLの改善を提案します - 適切なARIA属性を実装します - キーボード操作をサポートできるようにします - 色のコントラスト比を検証します - スクリーンリーダーとの互換性をテストします - アクセシビリティ監査レポートを生成します ## アクセシビリティレビューの手順ステップ1:セマンティックHTMLの監査
適切なセマンティック要素が使われているか、コンポーネントの構造をレビューします。
確認項目:
- 汎用的な
<div>ではなく、<header>、<nav>、<main>、<article>、<section>、<aside>、<footer>を使用していること - クリック可能な要素に
<div onclick>ではなく<button>を使用していること - ナビゲーションリンクに
<a>を使用していること - フォームに
<form>、<input>、<label>を使用していること - 見出しの階層(
<h1>から<h6>まで)が適切であること
例:
<div class="header">
<div claass="nav">
<div class="nav-item" onclick="navigate()">Home</div>
</div>
</div>
<header>
<nav>
<a href="/">Home</a>
</nav>
</header>
ステップ2:ARIA属性のレビュー
セマンティックHTMLだけでは不十分な場合に限り、ARIA属性を追加します。
一般的なパターン:
| 用途 | ARIA属性 | 例 |
|---|---|---|
| カスタムボタン | role="button"、tabindex="0" | <div role="button" tabindex="0"> |
| モーダルダイアログ | role="dialog"、aria-modal="true" | <div role="dialog" aria-modal="true"> |
| アラート | role="alert"、aria-live="assertive" | <div role="alert">Error occurred</div> |
| タブパネル | role="tabpanel"、aria-labelledby | <div role="tabpanel" aria-labelledby="tab-1"> |
ルール:
- 冗長なARIA属性を追加しないでください(
<button role="button">は不要です) - テキストのないアイコンボタンには
aria-labelを使用します - 装飾要素には
aria-hidden="true"を使用します - 動的コンテンツには
aria-live領域を使用します
例:
<button aria-label="Close dialog">
<i class="icon-close" aria-hidden="true"></i>
</button>
<div role="alert" aria-live="assertive">Form submitted successfully</div>
ステップ3:キーボード操作のテスト
すべてのインタラクティブ要素がキーボードで操作できることを確認します。
要件:
- Tab:インタラクティブ要素を前方へ移動します
- Shift+Tab:後方へ移動します
- Enter/Space:ボタンやリンクを作動させます
- 矢印キー:コンポーネント内(タブ、メニュー、リストボックス)を移動します
- Escape:ダイアログやメニューを閉じます
フォーカス管理:
- モーダル内にフォーカスを閉じ込めます(外部へTab移動できないようにします)
- モーダルを閉じたときに、フォーカスを起動元の要素に戻します
- スクリーンリーダー利用者向けに、メインコンテンツへのスキップリンクを設けます
- フォーカスインジケーターを視認できるようにします(
:focusスタイル)
例:
// Focus trap in modal
function openModal(modal) {
modal.style.display = 'block';
const firstFocusable = modal.querySelector('button, input, a');
firstFocusable.focus();
trapFocus(modal); // Prevent escape from modal
}
function trapFocus(container) {
const focusableElements = container.querySelectorAll('button, input, select, textarea, a[href]');
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
container.addEventListener('keydown', e => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
lastElement.focus();
e.preventDefault();
} else if (!e.shiftKey && document.activeElement === lastElement) {
firstElement.focus();
e.preventDefault();
}
}
});
}
ステップ3B:WCAG 2.2の新しい成功基準(2023年10月、ISO/IEC 40500:2025)
WCAG 2.2では、新しい成功基準が9項目追加されました。該当する基準に準拠していることを確認します。
2.4.11 フォーカスが隠されないこと — 最低限(AA)
キーボードでフォーカスされた要素が画面内にスクロールされるとき、固定ヘッダー/フッターや重なり合うUIによって完全に隠されてはなりません。フォーカスされた要素の一部が常に表示されている必要があります。
/* Prevent focus from hiding behind sticky headers */
:focus-visible {
scroll-margin-top: 80px; /* Height of sticky header + buffer */
scroll-margin-bottom: 60px; /* Height of sticky footer + buffer */
}
**テスト:**すべてのインタラクティブ要素をTabで順に移動し、バナー、Cookie通知、固定バーの背後に完全に隠れる要素がないことを確認します。
2.4.12 フォーカスが隠されないこと — 強化(AAA)
フォーカスされたコンポーネントは、部分的に表示されるだけでなく、全体が見えている必要があります。固定UIがフォーカスと重なってはなりません。
2.4.13 フォーカスの外観(AAA)
フォーカスインジケーターは、フォーカスされていないコンポーネントの周囲長に2 CSSピクセルを掛けた値以上の面積を持ち、フォーカス状態と非フォーカス状態のコントラスト比が少なくとも3:1である必要があります。
/* Meeting 2.4.13 Focus Appearance (AAA) */
:focus-visible {
outline: 3px solid #005fcc;
outline-offset: 2px;
/* 3px thickness > 2px minimum; #005fcc on white = 7.1:1 contrast */
}
#### 2.5.7 ドラッグ操作(AA)
すべてのドラッグ&ドロップ機能には、単一ポインター(クリック/タップ)で操作できる代替手段を必ず用意する必要があります。ドラッグ操作を正確に行えないユーザーも、同じタスクを完了できなければなりません。
<ul>
<li draggable="true" id="item-1">
Item 1
<button aria-label="Move Item 1 up" onclick="moveUp('item-1')">↑</button>
<button aria-label="Move Item 1 down" onclick="moveDown('item-1')">↓</button>
</li>
</ul>
<input type="range" min="0" max="100" value="50" aria-label="Volume" />
<input type="number" min="0" max="100" value="50" aria-label="Volume value" />
テスト: すべてのドラッグ操作を特定します。それぞれにドラッグ以外の代替手段(ボタン、コンテキストメニュー、キーボードショートカット)があることを確認します。
2.5.8 ターゲットサイズ — 最小(AA)
すべてのポインターターゲット(ボタン、リンク、チェックボックス、ラジオボタン)は、24x24 CSS ピクセル以上である必要があります。または、24x24 の領域が他のターゲットと重ならないよう、十分な間隔を空ける必要があります。
/* Ensure minimum target size */
button,
a,
input[type='checkbox'],
input[type='radio'],
select {
min-width: 24px;
min-height: 24px;
}
/* Inline links: use padding to increase hit area without visual size change */
a {
padding: 4px 0;
}
/* Recommended: 44x44 CSS pixels for primary actions (mobile-friendly) */
.primary-action {
min-width: 44px;
min-height: 44px;
}
テスト: すべてのインタラクティブ要素を測定します。24x24 CSS ピクセル未満の要素がないことを確認します(ブラウザーの DevTools 要素インスペクターを使用します)。
3.2.6 一貫したヘルプ(A)
ヘルプ機能(問い合わせリンク、チャットウィジェット、電話番号、FAQ リンク)が複数のページに表示される場合、ページコンテンツ内で同じ相対的な順序で表示する必要があります。
<footer>
<nav aria-label="Help resources">
<a href="/faq">FAQ</a>
<a href="/contact">Contact Support</a>
<a href="tel:+18005551234">1-800-555-1234</a>
</nav>
</footer>
テスト: ページ間を移動します。ヘルプリンク/ウィジェットが毎回同じ順序で表示されることを確認します。
3.3.7 重複入力(A)
ユーザーが以前に入力した情報は、同じセッション/プロセス内で同じ情報が再び求められたときに、自動入力されるか選択できるようにする必要があります(例:複数ステップの購入手続きフォーム)。
<fieldset>
<legend>Billing Address</legend>
<label>
<input type="checkbox" id="same-as-shipping" />
Same as shipping address
</label>
</fieldset>
例外: セキュリティ確認のためにパスワードを再入力する場合、リストから項目を選択する場合。
3.3.8 アクセシブルな認証 — 最低限(AA)
アクセシブルな代替手段が用意されている場合を除き、認証プロセスで認知機能テスト(パズルを解く、画像を識別する、コードを記憶/書き写す)をユーザーに要求してはなりません。
許容される代替手段:
- 生体認証(指紋、顔認証)
- メールのマジックリンク/SMS OTP(ユーザーはコードを覚える必要はなく、コピー&ペーストするだけです)
- サードパーティープロバイダー経由の OAuth
- パスワードマネージャーを使用可能にする(パスワードフィールドへの貼り付けをブロックしない)
<input type="password" id="password" autocomplete="current-password" />
<div role="group" aria-labelledby="captcha-label">
<span id="captcha-label">Verify you are human</span>
<img src="captcha.png" alt="CAPTCHA challenge" />
<input type="text" aria-describedby="captcha-label" />
<a href="?audio-captcha">Use audio CAPTCHA instead</a>
<a href="?email-login">Use email link instead</a>
</div>
テスト: すべての認証手順を特定します。代替手段なしで認知機能テストを要求する手順がないことを確認します。
3.3.9 アクセシブルな認証 — 例外なし(AAA)
代替手段が用意されていても、認知機能テストを要求してはなりません。
ステップ 4:色のコントラストを確認する
すべてのテキストが WCAG のコントラスト比を満たしていることを確認します。
基準:
| テキストサイズ | WCAG AA | WCAG AAA |
|---|---|---|
| 通常のテキスト(< 18pt) | 4.5:1 | 7:1 |
| 大きなテキスト(≥ 18pt または 14pt の太字) | 3:1 | 4.5:1 |
| UI コンポーネント | 3:1 | - |
ツール:
- WebAIM Contrast Checker
- ブラウザーの DevTools カラーピッカー
- グレースケールテスト(グレースケールに変換し、読みやすさを確認します)
例:
/* ❌ BAD - Innsufficient contrast */
.text {
color: #777;
background: #fff;
} /* 4.47:1 - fails AA */
/* ✅ GOOD - Sufficient contrast */
.text {
color: #595959;
background: #fff;
} /* 7:1 - passes AAA */
/* ✅ GOOD - Don't rely on color alone */
.error {
color: #d00;
border-left: 4px solid #d00; /* Visual indicator beyond color */
}
.error::before {
content: '⚠️ ';
} /* Icon indicator */
ステップ 5:スクリーンリーダーのサポート
スクリーンリーダーで適切に利用できることを確認します。
画像の代替テキスト:
<img src="logo.png" />
<img src="decorative.png" alt="decorative image" />
<img src="logo.png" alt="Company y Logo" />
<img src="decorative.png" alt="" role="presentation" />
アイコンボタンの ARIA ラベル:
<button><i class="icon-delete"></i></button>
<but tton aria-label="Delete item">
<i class="icon-delete" aria-hidden="true"></i>
</button>
動的コンテンツのライブリージョン:
<div role="alert" aria-live="assertive">Error: Invalid email address</div>
<div aria-live="polite" aria-atomic="true">Loading results... 3 of 10 loaded</div>
ステップ 6:フォームのアクセシビリティ
すべてのフォーム入力に適切なラベルが設定され、検証されることを確認します。
要件:
- すべての入力に対応する
<label>要素がある - グループ化された入力には
<fieldset>と<legend>を使用する - 検証エラーを
aria-describedbyで表示する - 必須フィールドには
aria-required="true"またはrequired属性を設定する
例:
<form>
<fieldset>
<legend>Personal Information</legend>
<label for="name">Name (required)</label>
<input id="name" type="textt" required aria-required="true" aria-describedby="name-error" />
<span id="name-error" role="alert" class="error" aria-live="polite">
</span>
<label for="email">Email</label>
<input id="email" type="email" aria-describedby="email-hint" />
<span id="email-hint" class="hint">We'll never share your email</span>
</fieldset>
</form>
ステップ 7:アクセシビリティレポートを生成する
次の内容を記録します。
- 検出された問題の総数(重大度別)
- WCAG レベルへの準拠状況(A、AA、AAA)
- 行番号を含む具体的な違反内容
- コード例を含む修正の推奨事項
- 実施したテスト(自動+手動)
例 1:React コンポーネントのレビュー
Skill({ skill: 'accessibility' });
入力:カスタムモーダルを含む React コンポーネント 出力:
- セマンティック HTML に関する推奨事項
- 必要な ARIA 属性
- キーボードナビゲーションの問題
- フォーカストラップの実装
- WCAG 準拠レポート
例 2:色のコントラストを監査する
Skill({ skill: 'accessibility', args: 'color-contrast' });
入力:色の定義を含む CSS ファイル 出力:
- コントラスト比が基準を満たさない箇所の一覧
- 推奨する色の調整
- 調整前後のコントラストスコア
例 3:フォームのアクセシビリティチェック
Skill({ skill: 'accessibility', args: 'forms' });
入力:フォームコンポーネント 出力:
- ラベルの関連付けの検証結果
- 必須フィールドの表示
- エラーメッセージのパターン
- キーボードでの送信への対応
<best_practices>
ベストプラクティス
するべきこと
- セマンティック HTML を基盤として使用します(header、nav、main、article)
- セマンティック HTML だけでは不十分な場合にのみ ARIA を追加します
- 実際のスクリーンリーダー(NVDA、JAWS、VoiceOver)でテストします
- マウスを使わずにキーボードで操作できるようにします
- 通常のテキストのコントラスト比を 4.5:1 に保ちます(WCAG AA)
- テキスト以外のすべてのコンテンツにテキストによる代替を用意します
- フォーカスインジケーター(視認できる :focus-visible スタイル)を使用します
- モーダル内にフォーカスを閉じ込めます
- aria-live で動的コンテンツを通知します
- スティッキーヘッダー/フッターによってフォーカス中の要素が隠れないようにします(WCAG 2.2 2.4.11)
- すべてのドラッグ操作にキーボード/クリックでの代替手段を用意します(WCAG 2.2 2.5.7)
- すべてのポインターターゲットを少なくとも 24x24 CSS ピクセルのサイズにします(WCAG 2.2 2.5.8)
- パスワードフィールドへの貼り付けを許可します。決してブロックしないでください(WCAG 2.2 3.3.8)
- 複数ステップのプロセスでは、以前に入力したデータを自動入力します(WCAG 2.2 3.3.7)
- ページ間でヘルプ機能を一貫した順序で配置します(WCAG 2.2 3.2.6)
してはいけないこと
- あらゆる用途に
<div>を使います(セマンティックな意味がありません) - インタラクティブでない要素にクリックハンドラーを設定します
- 画像の alt テキストを忘れます
- 情報を色だけに頼って伝えます
- フォーカスインジケーターを削除します(outline: none)
- コントロールなしでメディアを自動再生します
tabindexに 0 より大きい値を指定します(自然なタブ順序が乱れます)- キーボードトラップを作成します(ユーザーが抜け出せません)
- スクリーンリーダーから重要なコンテンツを隠します
アンチパターン
| アンチパターン | 問題 | 修正 |
|---|---|---|
<div onclick> | キーボードで操作できません | <button> を使用します |
| alt テキストがない | スクリーンリーダーで内容を説明できません | 意味のある alt 属性を追加します |
| 色だけで情報を示す | 色覚障害のあるユーザーには伝わりません | テキスト/アイコンを追加します |
| フォーカスインジケーターがない | ユーザーがナビゲーション中に現在位置を見失います | :focus-visible スタイルを追加します |
| メディアの自動再生 | スクリーンリーダーの利用を妨げます | コントロールと一時停止オプションを追加します |
あらゆる用途に <div> を使用 | セマンティックな構造がありません | セマンティック HTML を使用します |
| スクロールマージンのないスティッキーヘッダー | フォーカスがスティッキーバーの背後に隠れます(2.4.11) | :focus-visible に scroll-margin-top を追加します |
| ドラッグ操作のみで並べ替え可能なリスト | 運動障害のあるユーザーは並べ替えられません(2.5.7) | 各項目に上/下ボタンを追加します |
| 16x16px のアイコンボタン | 最小ターゲットサイズの 24x24 を下回っています(2.5.8) | min-width: 24px; min-height: 24px を設定します |
| 代替手段のない CAPTCHA | 認証における認知的な障壁です(3.3.8) | メールのマジックリンクまたはパスキーを選択肢として用意します |
onpaste="return false" | パスワードマネージャーからの貼り付けをブロックします(3.3.8) | パスワードフィールドでの貼り付けブロックを削除します |
| チェックアウトでフォームフィールドが重複している | 冗長なデータ入力が発生します(3.3.7) | 以前に入力した値を自動入力します |
アクセシビリティレビューを完了する前に、以下を確認してください。
WCAG 2.1 AA(既存の要件):
- すべての画像に代替テキストがある(装飾目的の場合は
alt="") - すべてのインタラクティブ要素をキーボードで操作できる
- タブの移動順序が論理的である
- フォーカスインジケーターが表示される
- 色のコントラストが WCAG AA の基準を満たしている(通常の文字は 4.5:1、大きな文字は 3:1)
- セマンティック HTML を使用している(nav、main、article など)
- アイコンボタンに ARIA ラベルがある
- フォームに適切なラベルがある
- エラーメッセージがスクリーンリーダーに通知される
- ダイアログ内にフォーカスを閉じ込め、Escape キーで閉じられる
- 動的コンテンツで ARIA ライブリージョンを使用している
- スクリーンリーダー(NVDA、JAWS、VoiceOver)でテスト済みである
- キーボードのみ(マウスなし)でテスト済みである
- ブラウザーのズーム(200%)でテスト済みである
WCAG 2.2 AA(新しい要件 — 2023年10月、ISO/IEC 40500:2025):
- 2.4.11:フォーカスされた要素が固定ヘッダーやフッターに完全に隠されない
- 2.5.7:すべてのドラッグ操作に、シングルポインター(クリック/タップ)で操作できる代替手段がある
- 2.5.8:すべてのポインターターゲットが少なくとも 24x24 CSS ピクセルである
- 3.2.6:ヘルプ機能(チャット、連絡先、電話)がページ間で同じ順序で表示される
- 3.3.7:複数ステップのフォームで、以前に入力した情報が自動入力される
- 3.3.8:代替手段がない場合、認証に認知機能テスト(パズル/CAPTCHA)を求めない
- パスワード欄で貼り付けができる(onpaste="return false" で貼り付けをブロックしない)
- キーボードフォーカスが固定 UI に隠されないよう、フォーカス時のスクロールマージンを設定する </best_practices>
絶対に守るべき原則
- 必ずセマンティック HTML から始める — 適切なネイティブ要素(
<button>、<nav>、<main>など)を使う前に ARIA に頼らないでください。 - フォーカスインジケーターを決して削除しない — 代替手段なしで
outline: noneを指定すると、直ちに WCAG 違反となります。キーボードユーザーは完全に操作方法を見失います。 - 必ず実際の支援技術でテストする — 自動化ツール(axe、Lighthouse)で検出できる問題は最大でも 30% です。NVDA、JAWS、または VoiceOver を使ったテストは必須です。
- 色だけで情報を伝えない — 色覚に障害のあるユーザーのために、色には必ずテキスト、アイコン、またはパターンを組み合わせてください。
- 必ず WCAG 2.2 AA の基準を適用する — 2.4.11(フォーカスが隠れない)、2.5.7(ドラッグ操作の代替手段)、2.5.8(24×24 のターゲットサイズ)、3.3.8(認知機能に関する認証障壁なし)は必須であり、任意ではありません。
統合ポイント
このスキルを使用するエージェント
- developer:アクセシブルなコンポーネントを実装します
- code-reviewer:PR のアクセシビリティをレビューします
- qa:アクセシビリティへの準拠をテストします
- frontend-pro:アクセシブルな UI パターンを確保します
- react-pro:React 固有のアクセシビリティパターンを扱います
関連スキル
- frontend-expert:UI コンポーネントのパターン
- react-expert:React のアクセシビリティパターン
- mobile-first-design-rules:タッチ操作のアクセシビリティ
ワークフロー
- feature-development-workflow.md:レビュー段階でアクセシビリティを確認します
- code-review-workflow.md:アクセシビリティチェックリスト
関連資料
.claude/rules/accessibility.md- アクセシビリティに関する完全なルール- WCAG 2.2 ガイドライン(現行標準)
- WCAG 2.2 の新機能
- WCAG 2.2 クイックリファレンス
- WebAIM コントラストチェッカー
- ARIA オーサリングプラクティス(APG)
- WCAG 2.2 実装完全ガイド(TestParty)
- 欧州アクセシビリティ法への準拠
メモリプロトコル(必須)
開始前:
cat .claude/context/memory/learnings.md
以下を確認してください:
- これまでに見つかったアクセシビリティのパターン
- このコードベースでよくあるアクセシビリティの問題
- プロジェクト固有のアクセシビリティ要件
完了後:
- 新しいアクセシビリティのパターン →
.claude/context/memory/learnings.md - 見つかったアクセシビリティの問題 →
.claude/context/memory/issues.md - 行ったアクセシビリティに関する判断 →
.claude/context/memory/decisions.md
中断されることを前提にしてください。コンテキストがリセットされる可能性があります。メモリに記録されていないことは、起きていないのと同じです。