web-accessibility-audit について
一般的なWCAG要件に照らしてWebアプリのアクセシビリティを確認するスキルです。自動チェック、コード調査、重要度に応じた整理、手動テストの指針を開発者や監査チームに提供します。
主な機能
- 01WCAG違反チェックリスト
- 02自動テストのガイダンス
- 03手動コード調査
- 04重要度に基づく優先順位付け
- 05支援技術テストのガイダンス
活用シーン
- 01サイトのWCAG課題の確認
- 02キーボード操作の障壁の調査
- 03フォーム、ラベル、コントラストの確認
- 04優先順位付きの修正手順の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ warpdotdev/ oz-skills --skill web-accessibility-auditインストール後、Claude Code で/web-accessibility-auditを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/ARIA-patterns.mdgrep-patterns.mdscreen-reader-guide.mdWCAG-criteria.mdscripts/run-eslint.sh詳細
アクセシビリティ監査
Web アプリケーションを監査し、よくある違反を特定して、具体的な修正方法を提示することで、WCAG 2.0/2.1/2.2 への準拠を確認します。
使用する場面
- ユーザーがアクセシビリティ監査、a11y チェック、または WCAG 準拠のレビューを依頼した場合
- ユーザーがアクセシビリティの問題、スクリーンリーダー、またはキーボード操作の問題に言及した場合
- ユーザーが障害のある人々のためにアクセシビリティを確認または改善したいと依頼した場合
WCAG の原則:POUR
| 原則 | 説明 |
|---|---|
| Perceivable(知覚可能) | さまざまな感覚を通じてコンテンツを知覚できます |
| Operable(操作可能) | すべてのユーザーがインターフェースを操作できます |
| Understandable(理解可能) | コンテンツとインターフェースを理解できます |
| Robust(堅牢) | コンテンツが支援技術で動作します |
適合レベル
| レベル | 要件 | 目標 |
|---|---|---|
| A | 最低限のアクセシビリティ | 適合必須 |
| AA | 標準的な準拠レベル | 適合が望ましい(一部の地域では法的要件です) |
| AAA | 高度なアクセシビリティ | 望ましい水準 |
よくある WCAG 違反 12 項目
上位 100 万件の Web サイトを分析した WebAIM Million(2021)の調査に基づきます。
-
色のコントラスト不足(WCAG 1.4.3) - サイトの 86.4%
- テキストのコントラスト比が 4.5:1 未満
- 大きなテキストのコントラスト比が 3:1 未満
- UI コンポーネントのコントラスト比が 3:1 未満
-
代替テキストの欠落/不適切(WCAG 1.1.1) - サイトの 60.6%
- alt 属性のない画像
- 「image」「picture」「photo」を含む代替テキスト
- 意味のある画像に対する空の alt 属性
-
名前、役割、または値の欠落(WCAG 4.1.2)
- アクセシブルな名前のないインタラクティブ要素
- 適切な ARIA を設定していないカスタムコンポーネント
- ボタン、フォームフィールド、カスタムウィジェット
-
キーボード操作の問題(WCAG 2.1.1)
- onClick はあるが、キーボードで操作できない要素
- フォーカスインジケーターの欠落
- キーボードフォーカスが閉じ込められる
-
フォームコントロールのラベル不足(WCAG 1.3.1、3.3.2) - サイトの 39.6%
<label>または aria-label のない入力欄- ラベルがプログラムで関連付けられていない
-
言語属性の欠落(WCAG 3.1.1) - サイトの 28.9%
<html>に lang 属性がない- 外国語の文章に lang 属性がない
-
見出し構造の不備(WCAG 1.3.1、2.4.6)
- 見出しレベルの飛ばし(h1 → h3)
- h1 が複数ある、または h1 がない
- 空の見出し
-
空のリンク、または不適切なリンクテキスト(WCAG 2.4.4)
- 「ここをクリック」「ここ」「続きを読む」といったリンク
- 空のリンク、またはアイコンのみのリンク
-
フォーカスインジケーターの欠落/不備(WCAG 2.4.7)
- 代替手段を用意せず CSS でアウトラインを削除している
- フォーカスインジケーターのコントラストが不十分
-
ARIA の過剰使用/誤用(WCAG 4.1.2)
- ネイティブ HTML で対応できる箇所に不要な ARIA を使用している
- 役割に対して無効な ARIA 属性を使用している
- 必須の ARIA 属性が欠落している
-
データテーブルのマークアップ不足(WCAG 1.3.1)
<th>要素のないテーブル- scope 属性または headers 属性の欠落
-
メディア字幕の欠落(WCAG 1.2.1、1.2.2)
- 字幕のない動画
- トランスクリプトのない音声
監査プロセス
フェーズ 1:自動テスト
ESLint を実行(React/JSX プロジェクト):
npx eslint --ext .jsx,.tsx --no-ignore --format json . > .claude/skills/a11y-auditor/eslint-results.json 2>&1 || true
またはヘルパースクリプトを使用します:.claude/skills/a11y-auditor/scripts/run-eslint.sh
Lighthouse を実行(本番環境/ステージング環境):
npx lighthouse https://example.com --only-categories=accessibility --output=json --output-path=./lighthouse-results.json
axe-core の統合を確認:
grep -r "@axe-core\|axe-core" package.json
フェーズ 2:コードの手動確認
references/grep-patterns.md の grep パターンを使用して、次の項目を検索します。
- 代替テキストの欠落
- キーボード操作の問題
- コントラスト確認用の色の値
- ARIA の問題
- フォームラベル
- 見出し構造
- 言語属性
- 不適切なリンクテキスト
- メディア要素
パターンの一覧は references/grep-patterns.md を参照してください。
フェーズ 3:分析と優先順位付け
WCAG の影響レベルに基づいて、検出事項を重大度別に分類します。
重大(直ちに修正):
- キーボードトラップ
- フォーカスインジケーターがない
- フォームラベルがない
- 機能を持つ画像に代替テキストがない
- インタラクティブ要素の色のコントラストが不十分
深刻(リリース前に修正):
- ページの言語が指定されていない
- 見出し構造が不適切
- リンクテキストが分かりにくい
- スキップリンクがない
- メディアが自動再生される
中程度(早めに修正):
- アイコンに ARIA ラベルがない
- ナビゲーションに一貫性がない
- エラーが特定されていない
- ランドマーク領域がない
フェーズ 4:手動テスト
次の項目については、references/screen-reader-guide.md に従ってください。
- キーボードナビゲーションのテスト
- スクリーンリーダーのテスト(VoiceOver、NVDA、JAWS)
- ズームとリフローのテスト
- ハイコントラストモードのテスト
- 動きを減らす設定のテスト
WCAG パターンの例
知覚可能
代替テキスト(1.1.1)
<img src="chart.png">
<img src="chart.png" alt="Bar chart showing 40% increase in Q3 sales">
<img src="decorative-border.png" alt="" role="presentation">
色のコントラスト(1.4.3)
/* ❌ Low contrast (2.5:1) */
.low-contrast {
color: #999;
background: #fff;
}
/* ✅ Sufficient contrast (7:1) */
.high-contrast {
color: #333;
background: #fff;
}
コントラスト要件:
- 通常のテキスト:4.5:1(AA)、7:1(AAA)
- 大きなテキスト(18px 以上、または 14px 以上の太字):3:1(AA)、4.5:1(AAA)
- UI コンポーネント:3:1
メディアの代替手段(1.2)
<video controls>
<source src="video.mp4" type="video/mp4">
<track kind="captions" src="captions.vtt" srclang="en" label="English" default>
</video>
操作可能
キーボードナビゲーション(2.1.1)
// ❌ Only click
element.addEventListener('click', handleAction);
// ✅ Click + keyboard
element.addEventListener('click', handleAction);
element.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleAction();
}
});
フォーカスの可視化(2.4.7)
/* ❌ Never remove focus */
*:focus { outline: none; }
/* ✅ Keyboard-only focus */
:focus-visible {
outline: 2px solid #005fcc;
outline-offset: 2px;
}
スキップリンク(2.4.1)
<body>
<a href="#main-content" class="skip-link">Skip to main content</a>
<header></header>
<main id="main-content" tabindex="-1">
</main>
</body>
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: #fff;
padding: 8px 16px;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
動きを減らす設定(2.3.3)
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
理解可能
ページの言語(3.1.1)
<html>
<html lang="en">
<p>The French word for hello is <span lang="fr">bonjour</span>.</p>
フォームラベル(3.3.2)
<input type="email" placeholder="Email">
<label for="email">Email address</label>
<input type="email" id="email" autocomplete="email">
<label for="password">Password</label>
<input type="password" id="password" aria-describedby="password-requirements">
<p id="password-requirements">
Must be at least 8 characters with one number.
</p>
エラー処理(3.3.1)
<label for="email">Email</label>
<input type="email" id="email"
aria-invalid="true"
aria-describedby="email-error">
<p id="email-error" role="alert">
Please enter a valid email address.
</p>
堅牢
ARIA の使用(4.1.2)
<button role="button">Submit</button>
<button>Submit</button>
<div role="tablist" aria-label="Product information">
<button role="tab" aria-selected="true" aria-controls="panel-1">
Description
</button>
<button role="tab" aria-selected="false" aria-controls="panel-2" tabindex="-1">
Reviews
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
</div>
ライブリージョン(4.1.3)
<div aria-live="polite" aria-atomic="true">
Status update
</div>
<div role="alert" aria-live="assertive">
Error: Form submission failed
</div>
視覚的に隠されたテキスト
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
<button>
<svg aria-hidden="true"></svg>
<span class="visually-hidden">Delete item</span>
</button>
出力形式
次の構成でレポートを生成します。
# Accessibility Audit Report
## Summary
- Total Issues: X
- Critical: X | Serious: X | Moderate: X | Minor: X
- WCAG Level: A, AA, or AAA
- Automated Coverage: ~57% (manual testing required)
## Critical Issues (Fix Immediately)
### 1. [Issue Name] - WCAG X.X.X
**Severity:** Critical
**Impact:** [Who is affected and how]
**Affected:** X elements
**Locations:**
- `path/to/file.tsx:123`
- `path/to/file.tsx:456`
**Problem:**
[Brief description]
**Fix:**
```tsx
// Before
<div onClick={handleClick}>Click me</div>
// After
<button onClick={handleClick}>Click me</button>
理由:[アクセシビリティの原則]
深刻な問題
[同じ形式]
中程度の問題
[同じ形式]
テストに関する推奨事項
- キーボードの手動テスト(Tab、Enter、Escape)
- スクリーンリーダーのテスト(references/screen-reader-guide.md を参照)
- 自動テストの設定(@axe-core/react または Lighthouse CI)
- 色のコントラストの検証(WebAIM Contrast Checker)
次のステップ
[優先順位を付けた対応項目]
---
## Tools & Resources
### Development Tools
- **eslint-plugin-jsx-a11y** - React/JSX static analysis (~37 rules)
- **axe-core DevTools** - Browser extension for runtime testing
- **Lighthouse** - Built into Chrome DevTools
### Testing Tools
- **@axe-core/react** - Runtime accessibility testing
- **@axe-core/playwright** - E2E test integration
- **pa11y** - Automated command-line testing
### Manual Testing
- **WebAIM Contrast Checker** - https://webaim.org/resources/contrastchecker/
- **WAVE** - Browser extension for visual feedback
- **Screen readers** - NVDA (Windows), VoiceOver (macOS), JAWS
### Reference Docs
- `references/WCAG-criteria.md` - All WCAG 2.1 success criteria
- `references/ARIA-patterns.md` - Common ARIA patterns and examples
- `references/screen-reader-guide.md` - Testing commands and scenarios
- `references/grep-patterns.md` - Search patterns for code audits
### References
- [WebAIM Million](https://webaim.org/projects/million/) - Annual analysis of top 1M websites (violation statistics)
- [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/) - Interactive WCAG guide
- [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/) - Official ARIA patterns
- [Deque axe Rules](https://dequeuniversity.com/rules/axe/) - All axe-core rules explained
- [jsx-a11y Rules](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y#supported-rules) - ESLint accessibility rules
---
## Important Notes
- Automated tools catch 30-57% of issues; manual testing required
- Pages with ARIA average 41% more errors than without
- Always test with actual assistive technology when possible
- Focus on critical issues first (keyboard, screen readers, contrast)
- Document deliberate accessibility decisions
- Test on multiple browsers and devices
- Include users with disabilities in testing when possible
## Common Pitfalls to Avoid
1. Relying solely on automated testing
2. Using ARIA when native HTML suffices
3. Removing focus indicators
4. Using positive tabindex values
5. Color as only means of conveying information
6. Keyboard traps in modals/dialogs
7. Non-descriptive link text
8. Missing or incorrect heading hierarchy
9. Unlabeled form controls
10. Missing language attributes