accessibility について
デザイナーや開発者向けのアクセシビリティガイドです。WCAG 2.2の原則、実装パターン、Lighthouseや手動テストのチェック項目をまとめています。
主な機能
- 01WCAG 2.2の原則と適合レベル
- 02キーボード操作とフォーカス管理
- 03コントラストとテキスト代替
- 04フォーム、エラー、ARIAのパターン
- 05自動・手動テストのチェック項目
活用シーン
- 01ページのアクセシビリティ要件を確認
- 02キーボード操作可能な画面を実装
- 03フォームとエラー表示を点検
- 04リリース前のテストを計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ thedesignproject/ agent-skills --skill accessibilityインストール後、Claude Code で/accessibilityを入力して読み込まれたか確認します。
同梱ファイルreferences/A11Y-PATTERNS.mdreferences/WCAG.md
詳細
アクセシビリティ(a11y)
WCAG 2.2 と Lighthouse のアクセシビリティ監査に基づく包括的なアクセシビリティガイドラインです。障害のある方を含むすべての人がコンテンツを利用できるようにすることを目指します。
WCAG の原則:POUR
| 原則 | 説明 |
|---|---|
| Perceivable(知覚可能) | さまざまな感覚を通じてコンテンツを知覚できます |
| Operable(操作可能) | すべてのユーザーがインターフェースを操作できます |
| Understandable(理解可能) | コンテンツとインターフェースを理解できます |
| Robust(堅牢) | コンテンツが支援技術で動作します |
適合レベル
| レベル | 要件 | 目標 |
|---|---|---|
| A | 最低限のアクセシビリティ | 適合必須 |
| AA | 標準的な適合性 | 適合が望ましい(多くの地域で法的要件) |
| AAA | 強化されたアクセシビリティ | あれば望ましい |
知覚可能
テキストによる代替(1.1)
画像には alt テキストが必要です:
<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">
<figure>
<img src="infographic.png" alt="2024 market trends infographic"
aria-describedby="infographic-desc">
<figcaption id="infographic-desc">
</figcaption>
</figure>
アイコンボタンにはアクセシブルな名前が必要です:
<button><svg></svg></button>
<button aria-label="Open menu">
<svg aria-hidden="true"></svg>
</button>
<button>
<svg aria-hidden="true"></svg>
<span class="visually-hidden">Open menu</span>
</button>
視覚的に隠すクラス:
.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;
}
色のコントラスト(1.4.3、1.4.6)
| テキストサイズ | AA 最低基準 | AAA 強化基準 |
|---|---|---|
| 標準テキスト(< 18px / < 14px 太字) | 4.5:1 | 7:1 |
| 大きなテキスト(≥ 18px / ≥ 14px 太字) | 3:1 | 4.5:1 |
| UI コンポーネントとグラフィック | 3:1 | 3:1 |
/* ❌ Low contrast (2.5:1) */
.low-contrast {
color: #999;
background: #fff;
}
/* ✅ Sufficient contrast (7:1) */
.high-contrast {
color: #333;
background: #fff;
}
/* ✅ Focus states need contrast too (3:1 against background, WCAG 1.4.11) */
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
色だけに頼らないでください:
<input class="error-border">
<style>.error-border { border-color: red; }</style>
<div class="field-error">
<input aria-invalid="true" aria-describedby="email-error">
<span id="email-error" class="error-message">
<svg aria-hidden="true"></svg>
Please enter a valid email address
</span>
</div>
メディアの代替(1.2)
<video controls>
<source src="video.mp4" type="video/mp4">
<track kind="captions" src="captions.vtt" srclang="en" label="English" default>
<track kind="descriptions" src="descriptions.vtt" srclang="en" label="Descriptions">
</video>
<audio controls>
<source src="podcast.mp3" type="audio/mp3">
</audio>
<details>
<summary>Transcript</summary>
<p>Full transcript text...</p>
</details>
操作可能
キーボードでの操作(2.1)
すべての機能をキーボードで操作できる必要があります。 ネイティブのインタラクティブ要素(<button>、<a href>、フォームコントロール)を優先してください。これらは Enter/Space による操作、フォーカス、支援技術向けのセマンティクスを標準で処理します。ネイティブ要素を使用できない場合に限り、キーボード操作を手動で追加してください。
<div class="card" onclick="handleAction()">Open</div>
<button type="button" onclick="handleAction()">Open</button>
// ✅ When you MUST use a non-interactive element (e.g. div with role="button"),
// make it focusable AND handle keyboard activation. Do NOT add this to a native
// <button> — Enter/Space already fire click, so you'd double-trigger.
element.setAttribute('role', 'button');
element.setAttribute('tabindex', '0');
element.addEventListener('click', handleAction);
element.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleAction();
}
});
キーボードトラップを作らないでください。 ユーザーはすべてのコンポーネントに Tab キーで移動して出入りできる必要があります。ダイアログにはモーダルのフォーカストラップパターンを使用してください。ネイティブの <dialog> 要素はこれを自動的に処理します。
フォーカスの可視化(2.4.7)
/* ❌ Never remove focus outlines */
*:focus { outline: none; }
/* ✅ Use :focus-visible for keyboard-only focus */
:focus {
outline: none;
}
:focus-visible {
outline: 2px solid currentColor; /* inherits text color → already contrast-checked */
outline-offset: 2px;
}
/* ✅ Or pick a brand color and verify ≥3:1 contrast against every background it lands on */
button:focus-visible {
box-shadow: 0 0 0 3px rgba(0, 95, 204, 0.5);
}
フォーカスを隠さない(2.4.11)— 2.2 で新設
要素がキーボードフォーカスを受け取ったとき、固定ヘッダーやフッター、重なり合うパネルなど、作成者が設置した他のコンテンツによって完全に隠されてはなりません。レベル AAA(2.4.12)では、フォーカスされた要素の一部も隠れてはなりません。
/* ✅ Account for sticky headers when scrolling to focused elements */
:target {
scroll-margin-top: 80px;
}
/* ✅ Ensure focused items clear fixed/sticky bars */
:focus {
scroll-margin-top: 80px;
scroll-margin-bottom: 60px;
}
スキップリンク(2.4.1)
キーボードユーザーが繰り返し表示されるナビゲーションを飛ばせるよう、スキップリンクを用意してください。マークアップとスタイルの詳細については、スキップリンクパターンを参照してください。
ターゲットサイズ(2.5.8)— 2.2 で新設
インタラクティブなターゲットは、24 × 24 CSS ピクセル以上である必要があります(AA)。例外:インラインテキストリンク、サイズがブラウザーによって制御される要素、境界ボックスの中央に配置した直径 24px の円が他のターゲットと重ならないターゲット。
/* ✅ Minimum target size */
button,
[role="button"],
input[type="checkbox"] + label,
input[type="radio"] + label {
min-width: 24px;
min-height: 24px;
}
/* ✅ Comfortable target size (recommended 44×44) */
.touch-target {
min-width: 44px;
min-height: 44px;
display: inline-flex;
align-items: center;
justify-content: center;
}
ドラッグ操作(2.5.7)— 2.2 で新設
ドラッグが必要な操作には、ポインターを 1 つだけ使う代替手段(例:ボタン、入力欄)を用意する必要があります。ソート可能なリストの例については、ドラッグ操作パターンを参照してください。
時間制限(2.2)
// Allow users to extend time limits
function showSessionWarning() {
const modal = createModal({
title: 'Session Expiring',
content: 'Your session will expire in 2 minutes.',
actions: [
{ label: 'Extend session', action: extendSession },
{ label: 'Log out', action: logout }
],
timeout: 120000
});
}
動き(2.3)
/* Respect reduced motion preference */
@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.2.3)
<nav aria-label="Main">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/products">Products</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
一貫したヘルプ(3.2.6)— 2.2 で新設
ヘルプ手段(連絡先情報、チャットウィジェット、FAQ リンク、セルフヘルプの選択肢)を複数のページで繰り返し表示する場合は、毎回同じ相対的な順序で表示する必要があります。配置の一貫性を頼りにするユーザーが、ページを開くたびにヘルプを探し回らなくて済むようにしてください。
フォームのラベル(3.3.2)
すべての入力欄には、プログラムで関連付けられたラベルが必要です。明示的、暗黙的、および説明的な例については、フォームのラベルパターンを参照してください。
エラー処理(3.3.1、3.3.3)
role="alert" または aria-live を使ってスクリーンリーダーにエラーを通知し、無効なフィールドには aria-invalid="true" を設定し、送信時には最初のエラーにフォーカスを移動してください。マークアップと JS の詳細については、エラー処理パターンを参照してください。
冗長な入力(3.3.7)— 2.2 で追加
同じセッション内でユーザーがすでに入力した情報を、再入力させないでください。前のステップで入力した情報を自動入力するか、以前に入力した値から選択できるようにしてください。例外:セキュリティ上の再確認、および有効期限が切れたコンテンツ。
<fieldset>
<legend>Shipping address</legend>
<label>
<input type="checkbox" id="same-as-billing" checked>
Same as billing address
</label>
</fieldset>
アクセシブルな認証(3.3.8)— 2.2 で追加
ログインフローでは、次のいずれかを満たさない限り、認知機能テスト(例:パスワードの記憶、パズルの解答)に依存してはなりません。
- コピー&ペーストまたは自動入力の仕組みを利用できる
- 代替手段がある(例:パスキー、SSO、メールリンク)
- テストでオブジェクト認識または個人的なコンテンツを使用する(AA のみ。AAA ではこの例外も認められません)
<input type="password" id="password" autocomplete="current-password">
<button type="button">Sign in with passkey</button>
<button type="button">Email me a login link</button>
堅牢性
ARIA の使用(4.1.2)
ネイティブ要素を優先してください:
<div role="button" tabindex="0">Click me</div>
<button>Click me</button>
<div role="checkbox" aria-checked="false">Option</div>
<label><input type="checkbox"> Option</label>
**ARIA が必要な場合は、**適切なロールと状態を使用してください。タブリストの完全な例については、ARIA タブのパターンを参照してください。
ライブリージョン(4.1.3)
フォーカスを移動せずに動的なコンテンツの変更を通知するには、aria-live リージョンを使用してください。マークアップと showNotification() ヘルパーについては、ライブリージョンのパターンを参照してください。
テストチェックリスト
自動テスト
# Lighthouse accessibility audit
npx lighthouse https://example.com --only-categories=accessibility
# axe-core
npm install @axe-core/cli -g
axe https://example.com
手動テスト
- **キーボード操作:**ページ全体を Tab キーで移動し、Enter キーまたは Space キーで操作します
- **スクリーンリーダー:**VoiceOver(Mac)、NVDA(Windows)、または TalkBack(Android)でテストします
- **ズーム:**ズーム率 200% でもコンテンツを利用できます
- **ハイコントラスト:**Windows のハイコントラストモードでテストします
- モーションの低減:
prefers-reduced-motion: reduceでテストします - **フォーカス順序:**論理的で、視覚的な順序に沿っています
- **ターゲットサイズ:**インタラクティブ要素が最小 24×24px を満たしています
VoiceOver と NVDA のショートカットについては、スクリーンリーダーのコマンドリファレンスを参照してください。
影響度別の一般的な問題
重大(直ちに修正)
- フォームラベルがない
- 画像の代替テキストがない
- 色のコントラストが不十分
- キーボードトラップ
- フォーカスインジケーターがない
深刻(公開前に修正)
- ページの言語が指定されていない
- 見出し構造がない
- リンクテキストが説明的でない
- メディアが自動再生される
- スキップリンクがない
中程度(早めに修正)
- アイコンに ARIA ラベルがない
- ナビゲーションに一貫性がない
- エラーが特定されていない
- 制御手段のない時間制限
- ランドマークリージョンがない