はじめに
Webアクセシビリティは、すべてのユーザーが快適にWebサイトを利用できるようにするために欠かせない要素です。特に、高齢者や視覚・聴覚障害を持つユーザーにとって、適切なアクセシビリティ対応が行われていないと、情報へのアクセスが制限されてしまいます。
本記事では、Lighthouseやaxeを活用したアクセシビリティテストの自動化、WCAGガイドラインに基づく評価基準の整備、スクリーンリーダー対応の改善、カラーコントラストの最適化、ARIAランドマークの導入など、Webアクセシビリティ向上のための具体的な方法を詳しく解説します。これらの取り組みを継続的に行うことで、より多くのユーザーにとって使いやすいWebサイトを実現しましょう。
アクセシビリティテストの自動化(Lighthouse / axe での監視設定)
アクセシビリティテストを自動化することで、継続的な品質保証が可能になります。特に、Lighthouse と axe-core は、開発フローに組み込みやすい代表的なツールです。
Lighthouse を使用したアクセシビリティテスト
Lighthouse は Google が提供するオープンソースの監査ツールで、以下の点を自動チェックできます。
- アクセシビリティ(ウェブコンテンツのユーザビリティ)
- パフォーマンス(ページ速度)
- SEO(検索エンジン最適化)
- ベストプラクティス(セキュリティやモバイル対応)
- PWA(プログレッシブウェブアプリの適合性)
Lighthouse の実行方法
- Chrome で対象ページを開く。
- F12 または Cmd + Option + I(Mac)/ Ctrl + Shift + I(Windows) で DevTools を開く。
- Lighthouse タブを選択し、"Accessibility" にチェックを入れる。
- Analyze page load をクリックして分析。
axe-core を使用したアクセシビリティテスト
Deque Systems が開発した axe-core
は、開発者向けのアクセシビリティテストツールで下記のような特徴があります。
- ウェブページのアクセシビリティ違反を細かく検出
- Jest や Cypress などのテストフレームワークと統合可能
- ブラウザ拡張機能としても利用可能(axe DevTools)
Cypress
+ axe-core
の組み合わせ
1. E2E テストツールの Cypress
でも cypress-axe
を使えばアクセシビリティテストを実行できます。
cypress-axe のインストール
npm install --save-dev cypress-axe
Cypress テストで axe-core を利用
describe("Accessibility check", () => {
it("Should have no detectable accessibility violations", () => {
cy.visit("https://example.com");
cy.injectAxe();
cy.checkA11y();
});
});
cy.injectAxe()
:axe-core
をページに読み込む。cy.checkA11y()
: ページのアクセシビリティ違反を検出。
メリット
✅ ページ全体のアクセシビリティ違反を検出
✅ 実際のブラウザ環境で検証できる
✅ キーボード操作やフォーカスの移動などのテストも可能
Playwright
+ axe-core
を使う
2. Cypress
以外にも、Playwright
を使った E2E テストの中で axe-core
を利用する方法があります。
Playwright
+ axe-core
のインストール
npm install --save-dev @playwright/test @axe-core/playwright
Playwright
テストで axe-core
を利用
import { test, expect } from "@playwright/test";
import { injectAxe, checkA11y } from "@axe-core/playwright";
test("Page should be accessible", async ({ page }) => {
await page.goto("https://example.com");
await injectAxe(page);
await checkA11y(page);
});
Lighthouse
と axe-core
の使い分け
ツール | 用途・特徴 |
---|---|
Lighthouse | アクセシビリティスコアの算出とレポート生成が得意。全体の改善点を把握するのに向いている。 |
axe-core | アクセシビリティ違反を詳細に検出し、Jest や Cypress での自動テストに適している。 |
アクセシビリティ評価基準の整備(WCAG ガイドラインに基づく基準策定)
Webアクセシビリティの評価基準は、WCAG(Web Content Accessibility Guidelines) に基づいて策定されます。WCAG は、すべてのユーザーがウェブコンテンツにアクセスできるようにするための国際的なガイドラインであり、主に 4つの原則 に基づいています。
WCAGの4つの原則
1. 知覚可能(Perceivable)
ユーザーがコンテンツを 視覚・聴覚・触覚などを通じて認識できるようにする。
- 例
- 画像 に 代替テキスト(alt属性) を設定する。
- 動画・音声 に 字幕や文字起こし を提供する。
- コントラスト比 を十分に確保する(例:テキストと背景の色のコントラスト比 4.5:1 以上)。
- スクリーンリーダー で情報が正しく読み上げられるようにマークアップする。
2. 操作可能(Operable)
すべてのユーザーがコンテンツを操作できるようにする。
- 例
- キーボード操作 に対応させる(マウスなしでも利用可能)。
- フォーカス管理 を適切に設定する(タブキーでのナビゲーションを明確に)。
- 制限時間付きの操作 に対する猶予を設ける(自動ログアウトやポップアップに十分な時間を与える)。
- 点滅や強いアニメーション を抑える(光過敏性発作を引き起こさないようにする)。
3. 理解可能(Understandable)
ユーザーが コンテンツを理解できる ようにする。
- 例
- 簡潔でわかりやすい言葉を使用する。
- フォームのエラーメッセージ を明確に伝える(例:「入力が必要です」ではなく「メールアドレスを正しく入力してください」)。
- ナビゲーションの一貫性を保つ(ページごとに異なるレイアウトを避ける)。
4. 堅牢(Robust)
支援技術と互換性 があり、将来的にも使用できるようにする。
- 例
- 適切なHTMLマークアップ(見出しタグ h1~h6 の適切な使用、ARIA属性の活用)。
- 最新のWeb技術 に対応する(例:JavaScriptがなくても基本的な操作ができる)。
- テストを複数の支援技術(スクリーンリーダー、音声入力ソフトなど)で実施する。
企業がアクセシビリティ評価基準を整備するメリット
- ユーザー体験(UX)の向上
アクセシビリティを向上させることで、より多くの人が快適に利用可能。 - 法規制の遵守
日本:「障害者差別解消法」に基づく合理的配慮の提供。
EU:「European Accessibility Act(EAA)」に準拠。
アメリカ:「ADA(Americans with Disabilities Act)」や「Section 508」などの基準。 - SEO(検索エンジン最適化)への影響
適切なHTML構造やaltテキストの設定はSEOにもプラス。 - 企業の社会的責任(CSR)
インクルーシブなデザインは企業のブランド価値向上に貢献。
企業内での評価基準の策定手順
1. WCAGの適用レベルを決定
WCAGには A、AA、AAA の3つの適用レベルがある。
- A(最低基準):最低限のアクセシビリティ要件を満たす(例:画像のalt設定)。
- AA(推奨基準):多くのユーザーが利用できる基準(例:色のコントラスト比の確保)。
- AAA(高度基準):高水準のアクセシビリティを確保(例:手話翻訳の提供)。
2. 自社製品に適した評価基準を文書化
- 企業の業務やターゲットユーザーに応じた基準を策定。
- 評価基準ドキュメント を作成し、社内の関係者と共有。
例)評価基準の文書化
項目 | 説明 | 適用レベル |
---|---|---|
画像のalt属性 | すべての画像に適切なaltを設定する | A |
キーボード操作 | すべてのUI要素がキーボードで操作可能であること | AA |
色のコントラスト比 | 4.5:1以上(テキストと背景) | AA |
フォームのラベル | 入力欄には明確なラベルを付与する | AA |
動画の字幕 | すべての動画に字幕を提供する | AAA |
3. 自動テスト + 手動テストの組み合わせで定期的な評価を実施
- 自動テスト
- Axe、Lighthouse、WAVE などのツールを活用して定期的にスキャン。
- 手動テスト
- キーボードのみでの操作確認。
- スクリーンリーダー(NVDA、VoiceOver、JAWS)での検証。
- ユーザビリティテスト(実際のユーザーによる評価)。
4. 監査結果をドキュメント化し、改善サイクルを確立
- 監査レポート を作成し、問題点と改善策を明確にする。
- 改善計画を策定し、定期的にレビュー(例:四半期ごとのアクセシビリティレビュー)。
キーボード操作の確認(全ての機能がキーボードで操作可能か確認)
キーボード操作の確認は、アクセシビリティ(A11Y)を向上させるために不可欠です。特に、マウスが使えないユーザーやスクリーンリーダーを利用するユーザーにとって、キーボードだけで全機能を利用できることが求められます。
キーボード操作の確認ポイント
1. Tab キーで全てのインタラクティブ要素を移動できるか
tab
キーを押すと、ページ内のボタン、リンク、入力欄などの フォーカス可能な要素 に移動できる必要があります。Shift + Tab
で逆順に移動できるかも確認します。- tabindex="-1" の要素はフォーカスされないため、必要に応じて tabindex="0" を設定。
2. Enter / Space でボタンが押せるか
- ボタン (
<button>
,<a href>
,<input type="submit">
) は Enter または Space でアクションが実行できるか確認します。 div
やspan
をボタンの代わりに使っている場合、role="button"
を付けるだけでは不十分です。keydown
イベントでEnter
やSpace
をハンドリングする必要あります。
3. Escape キーでモーダルを閉じられるか
- モーダルウィンドウが開いているときに
Escape
を押したら閉じる仕様になっているか確認。 aria-hidden
やaria-modal="true"
の設定が適切かチェックします。
4. フォーカスインジケーター(アウトライン)が適切に表示されるか
outline: none
を指定していないか確認(見た目だけでなく、視認性を確保することが重要)。- カスタムフォーカススタイルを適用する場合、
:focus-visible
を利用するとマウス操作時には非表示にできる。
button:focus-visible {
outline: 2px solid #005fcc; /* アクセシブルなフォーカス色 */
border-radius: 4px;
}
手動テストによる確認
tab
キーを使用してフォーカスの移動を確認します。
自動テストによる確認
Cypress は E2E テストに便利なツールで、キーボード操作のテストも可能です。
describe('Keyboard Navigation Test', () => {
it('should allow navigation via Tab key', () => {
cy.visit('https://example.com');
cy.get('button').first().focus().should('have.css', 'outline');
cy.tab().should('have.focus'); // Tabキーで次の要素に移動
});
it('should close modal on Escape key press', () => {
cy.get('#open-modal').click();
cy.get('#modal').should('be.visible');
cy.get('body').type('{esc}');
cy.get('#modal').should('not.exist');
});
});
Playwright は keyboard.press()
を使って詳細なキーボード操作をテストできます。
import { test, expect } from '@playwright/test';
test('Keyboard navigation works correctly', async ({ page }) => {
await page.goto('https://example.com');
// Tabキーでボタンをフォーカス
await page.keyboard.press('Tab');
await expect(page.locator('button')).toBeFocused();
// Enterキーでクリックしモーダルが表示される
await page.keyboard.press('Enter');
await expect(page.locator('#modal')).toBeVisible();
// Escapeキーでモーダルを閉じる
await page.keyboard.press('Escape');
await expect(page.locator('#modal')).not.toBeVisible();
});
カラーコントラストの最適化(色盲や視力低下者向けに高コントラストを確保)
カラーコントラストの重要性
- 視覚障害者や色覚異常(色盲)の方にも読みやすい・区別しやすいサイトを作るために必要です。文字色と背景色のコントラストが不十分だと、文字が判別しづらくなります。
- 高齢者や視力の低下がある方にも有効で、しっかり文字情報を伝えられるようになり、アクセシビリティが向上します。
- WCAG(Web Content Accessibility Guidelines)2.1では、文字の可読性と判別性を高めるため、特定のコントラスト比を遵守することを推奨しています。
こうした配慮は「見る人みんなが心地よく読みやすい」ウェブサイトを作る土台になります。あなたがその価値を理解し、丁寧に取り組むことで、多くのユーザーが助かり、その結果サービス全体の満足度も向上します。
推奨されるコントラスト比
- 通常のテキスト: コントラスト比 4.5:1 以上
- 大きなテキスト(18px 以上 or 14px 太字): コントラスト比 3:1 以上
「コントラスト比」とは、背景色と前景色(文字色)の明暗差を数値化したものです。この比率が高いほど、両色の違いがはっきりと認識できる、つまり読みやすいということになります。
例)
- 黒文字(#000000) と 白背景(#FFFFFF) のコントラスト比は 21:1 と最高レベル
- グレー文字(#767676) と 白背景(#FFFFFF) だとコントラスト比が低めになるため、場合によっては基準を満たせないこともありえます
テストツール
-
Lighthouse
- Google Chromeの開発者ツールに搭載されている監査ツール。
- 「Accessibility」項目の中でカラーコントラストに関する指摘があれば表示されます。
-
axe DevTools
- Deque Systemsが提供しているブラウザ拡張機能。
- ページをスキャンして、自動でアクセシビリティの問題点をリストアップ。コントラスト違反も見つけやすいです。
-
Contrast Checker
- 「WebAIM’s Contrast Checker」などのオンラインツール。
- 手動で色のコードを入力すると、コントラスト比と合否をチェックできます。
- デザイナーとやり取りする際、具体的な数値で「この色はコントラスト比4.2:1なので、あともう少し明るくしましょう」などと提案しやすくなります。
スクリーンリーダー対応の改善(alt 属性の適切な設定)
特に画像 (<img>
タグ) に適切な alt
属性を設定することは、スクリーンリーダー利用者にとって不可欠です。以下のルールを守ることで、アクセシビリティを向上させられます。
alt
属性の基本ルール
1. 装飾目的の画像(視覚的な飾りのみ)
alt=""
(空にする)role="presentation"
を併用すると、スクリーンリーダーが完全に無視- 例: 背景装飾としてのアイコン
<img src="decorative-icon.png" alt="" role="presentation">
2. 意味のある画像(情報提供を目的とする画像)
- 画像の内容を簡潔に説明する
alt
を設定 - role="presentation" を併用すると、スクリーンリーダーが完全に無視
- 例: 商品画像
<img src="product.jpg" alt="赤いスニーカー">
3, リンク内の画像
- alt にはリンク先の内容を説明するテキストを入れる
- 例: 企業ロゴがリンクになっている場合
<a href="https://example.com"> <img src="logo.png" alt="Example社のホームページへ"> </a>
4. テキストを含む画像
- 画像内のテキストを alt にそのまま書く
- 例: バナー画像
<img src="sale-banner.jpg" alt="全商品20%オフ!今週末まで">
5. 図やグラフ
- alt には要約を記載し、詳細な説明は figcaption や longdesc を活用
- 例: グラフ
<figure> <img src="sales-chart.png" alt="売上の推移を示す棒グラフ"> <figcaption>2024年1月から3月の売上推移</figcaption> </figure>
ARIA 属性を活用したアクセシビリティ強化
alt
属性だけでは対応しきれないケースでは、ARIA (aria-*
) 属性を活用することで、スクリーンリーダーが正しく情報を伝えられるようにできます。
aria-label
/ aria-labelledby
-
aria-label
: 要素に直接ラベルを付ける<button aria-label="メニューを開く">☰</button>
-
aria-labelledby
: 他の要素を参照してラベルを付ける<h2 id="section-title">製品一覧</h2> <section aria-labelledby="section-title"> <p>最新の製品ラインナップをご紹介します。</p> </section>
aria-live
(ライブリージョン)
aria-live
(ライブリージョン)は、スクリーンリーダーに対して「このエリアの内容が変わったら、ユーザーに通知して」と指示するための属性です。
Webページ上のコンテンツが動的に変わる場合、視覚的には変化がわかっても、スクリーンリーダーには通知されません。
そのため、aria-live
を適用することで、スクリーンリーダーに変更を伝えることができます。
<p id="status" aria-live="polite">カートに商品がありません。</p>
<button onclick="document.getElementById('status').textContent = '商品がカートに追加されました!'">
カートに追加
</button>
- ページを開くと、スクリーンリーダーは カートに商品がありません と読み上げる。
- ボタンを押すと
<p>
の内容が 商品がカートに追加されました! に変わる。 aria-live="polite"
によって、スクリーンリーダーは適切なタイミングで 商品がカートに追加されました! を読み上げる。
スクリーンリーダーテスト方法
スクリーンリーダーを使ったテスト
- Windows: NVDA
- Mac: VoiceOver(
Command + F5
で起動) - iPhone / iPad: VoiceOver(
設定 > アクセシビリティ > VoiceOver
)
テストのポイント
alt
が適切に読み上げられるかaria-label
/aria-labelledby
の動作確認- 重要な情報が
aria-live
で適切に伝達されるか
自動テストツール
axe-core
を使うと、アクセシビリティの問題を効率的に検出できる。
- Chrome拡張機能「
axe DevTools
」をインストール - DevTools(
F12
)を開き、「axe DevTools」を実行 alt
のない画像やaria-*
属性の誤りを検出
ARIA ランドマークの導入
ARIA(Accessible Rich Internet Applications)ランドマークは、Webページの主要なセクションをスクリーンリーダーや支援技術が認識しやすくするための重要な役割を果たします。適切に設定することで、視覚障害のあるユーザーがページの構造をすばやく把握し、必要な情報へ効率的にアクセスできるようになります。
ランドマークの種類と適用方法
HTML5 では、すでに多くの要素が暗黙的に ARIA の役割を持っていますが、場合によっては明示的に role
属性を指定することで、スクリーンリーダーの挙動を強化できます。
要素 | デフォルトの役割 | 推奨される role | 説明 |
---|---|---|---|
<header> |
banner (条件付き) |
role="banner" |
サイト全体またはセクションのヘッダーを示す。 |
<nav> |
navigation |
role="navigation" |
ナビゲーションメニューを示す。 |
<main> |
main |
role="main" |
ページの主要なコンテンツ領域。 |
<aside> |
complementary |
role="complementary" |
補助的な情報(サイドバーなど)を提供。 |
<footer> |
contentinfo (条件付き) |
role="contentinfo" |
フッター(著作権情報など)を示す。 |
ポイント
<header>
や<footer>
は、ページ全体のヘッダー・フッターとして使われる場合のみrole="banner"
やrole="contentinfo"
の適用が推奨されます。(セクション内で使う場合は適用しない)<main>
は、ページ内に 1 つだけ 存在するよう設定します。<nav>
を複数設置する場合は、aria-label
を使ってどのナビゲーションかわかるようにするのが望ましいです。
コード例
以下のコードでは、適切に ARIA ランドマークを設定し、スクリーンリーダーが認識しやすい構造になっています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ARIAランドマークの詳細な例</title>
</head>
<body>
<!-- ヘッダー -->
<header role="banner">
<h1>サイトタイトル</h1>
</header>
<!-- グローバルナビゲーション -->
<nav role="navigation" aria-label="グローバルナビゲーション">
<ul>
<li><a href="#">ホーム</a></li>
<li><a href="#">製品情報</a></li>
<li><a href="#">サポート</a></li>
</ul>
</nav>
<div style="display: flex;">
<!-- メインコンテンツ -->
<main role="main">
<h2>主要コンテンツ</h2>
<p>このセクションには、ページの主要な情報が含まれます。</p>
</main>
<!-- 関連情報 -->
<aside role="complementary" aria-labelledby="related-info">
<h3 id="related-info">関連情報</h3>
<p>補助的な情報を提供します。</p>
</aside>
</div>
<!-- サブナビゲーション -->
<nav role="navigation" aria-label="サイドナビゲーション">
<ul>
<li><a href="#">利用ガイド</a></li>
<li><a href="#">FAQ</a></li>
</ul>
</nav>
<!-- フッター -->
<footer role="contentinfo">
<p>© 2025 会社名</p>
</footer>
</body>
</html>
ポイント
aria-labelledby="related-info"
を使用して、aside
内の補助情報が何に関連しているのかを明確にする。aria-label="グローバルナビゲーション"
やaria-label="サイドナビゲーション"
を使い、ナビゲーションの役割を区別する。div
でレイアウトを調整し、main
とaside
を横並びにする。
フォームのアクセシビリティ改善
フォームのラベルと入力フィールドを適切に関連付けることで、スクリーンリーダーを使用する視覚障害者やキーボード操作を行うユーザーにとって、より使いやすいフォームを設計できます。これにより、アクセシビリティの向上だけでなく、ユーザーエクスペリエンスの改善にもつながります。
label
要素を明示的に関連付ける
label
要素を for
属性を使って input
要素と関連付けることで、スクリーンリーダーがフォームの各入力フィールドを適切に読み上げるようになります。
<label for="username">ユーザー名</label>
<input type="text" id="username" name="username">
ポイント
label
のfor
属性の値を、対応するinput
のid
と一致させる。label
をinput
の隣に配置すると、視覚的にもわかりやすくなる。
メリット
- スクリーンリーダーが「ユーザー名、入力フィールド」と適切に読み上げる。
label
をクリックすると、関連するinput
にフォーカスが移動し、クリックしやすくなる。
aria-labelledby
を活用する
aria-labelledby
を使うことで、1つのラベルを複数の入力フィールドに関連付けたり、視覚的にlabel
を配置しづらい場合に代替として利用したりできます。
<div>
<span id="email-label">メールアドレス</span>
<input type="email" id="email" aria-labelledby="email-label">
</div>
ポイント
aria-labelledby
の値に、関連付ける要素のid
を指定する。label
要素が使えない場面(例えば、ボタンや複雑なフォームレイアウト)で有効。
メリット
label
なしでもスクリーンリーダーが適切に読み上げる。- 1つのラベルを複数のフィールドに関連付けることが可能。
aria-describedby
を活用する
補足説明を提供する場合に aria-describedby
を使用すると、入力フィールドの補足説明をスクリーンリーダーに伝えることができます。
<input type="text" id="phone" aria-describedby="phone-desc">
<span id="phone-desc">ハイフンなしで入力してください。</span>
ポイント
- aria-describedby の値に、補足説明の id を指定する。
- 使い方のヒントやエラーメッセージの説明を追加できる。
メリット
- ユーザーがフィールドにフォーカスしたときに、スクリーンリーダーが補足説明を読み上げる。
- エラーメッセージの伝達にも有効。
モーダルウィンドウの操作確認
モーダルウィンドウを適切に管理することで、キーボード操作の快適性とアクセシビリティを向上させることができます。本記事では、フォーカス制御の重要性と適切な実装方法について詳しく解説します。
モーダル内でフォーカスを適切に管理する
- 最初のフォーカスの移動
モーダルを開いた際に、適切なフォーカス要素(close ボタンや input フィールドなど)にフォーカスを移動させる。 - 背景コンテンツへのフォーカス防止
モーダルが開いている間、tab キーを押しても背景の要素にフォーカスが移動しないように制御する。 - Esc キーによるモーダルの閉鎖
ユーザーが Esc キーを押した際にモーダルを閉じられるようにする。
コード例(React + TypeScript 版モーダル)
import { useEffect, useRef } from "react";
interface ModalProps {
isOpen: boolean;
onClose: () => void;
}
const Modal: React.FC<ModalProps> = ({ isOpen, onClose }) => {
const modalRef = useRef<HTMLDivElement>(null);
const closeButtonRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
if (isOpen) {
// モーダルを開いたら最初のフォーカスを設定
setTimeout(() => {
closeButtonRef.current?.focus();
}, 0);
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape") {
onClose();
} else if (event.key === "Tab") {
// フォーカスをループさせる
const focusableElements = modalRef.current?.querySelectorAll(
'a[href], button, textarea, input, select'
) as NodeListOf<HTMLElement>;
if (!focusableElements) return;
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
if (event.shiftKey) {
if (document.activeElement === firstElement) {
event.preventDefault();
lastElement.focus();
}
} else {
if (document.activeElement === lastElement) {
event.preventDefault();
firstElement.focus();
}
}
}
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}
}, [isOpen, onClose]);
if (!isOpen) return null;
return (
<div
ref={modalRef}
role="dialog"
aria-hidden={!isOpen}
aria-labelledby="modal-title"
className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50"
>
<div className="bg-white p-6 rounded-lg shadow-lg w-96">
<h2 id="modal-title" className="text-lg font-bold mb-4">
モーダルタイトル
</h2>
<p className="mb-4">モーダルの内容をここに記述します。</p>
<button
ref={closeButtonRef}
onClick={onClose}
className="bg-red-500 text-white px-4 py-2 rounded"
>
閉じる
</button>
</div>
</div>
);
};
export default Modal;
ポイント
- モーダルの開閉を
isOpen
で管理isOpen
がtrue
のときのみ、モーダルを表示。isOpen
がfalse
の場合はnull
を返して非表示に。
- フォーカス管理
- モーダルが開かれたら、最初のフォーカスを 閉じる ボタンにセット。
Tab
キーでフォーカスをループさせる (firstElement
⇄lastElement
)。
- Esc キーで閉じる
keydown
イベントを監視し、Escape
キーが押されたらonClose()
を実行。
- アクセシビリティ対応
<div>
にrole="dialog"
を設定し、aria-hidden
でスクリーンリーダー対応。aria-labelledby="modal-title"
により、タイトルを読み上げられるように設定。
App.tsx
)
使用例 (モーダルを開閉するボタンを App.tsx
に配置し、useState
を利用して状態管理します。
import { useState } from "react";
import Modal from "./Modal";
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<div className="flex flex-col items-center justify-center h-screen">
<button
onClick={() => setIsModalOpen(true)}
className="bg-blue-500 text-white px-4 py-2 rounded"
>
モーダルを開く
</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} />
</div>
);
};
export default App;
このコードを適用すると、以下のような動作を確認できます。
- 「モーダルを開く」ボタンをクリックすると、モーダルが表示される。
- Tab キーを押すと、モーダル内の要素だけをフォーカス移動できる。
- Esc キーを押すと、モーダルが閉じる。
- モーダルが閉じると、元の「モーダルを開く」ボタンにフォーカスが戻る。
レスポンシブデザインの確認
レスポンシブデザインとは、異なるデバイスや画面サイズに応じて適切にレイアウトを調整する設計手法です。特にアクセシビリティ(利用しやすさ)を考慮することで、すべてのユーザーが快適に操作できるWebサイトを構築できます。ここでは、レスポンシブデザインの基本となる メディアクエリ と ビューポートメタタグ について詳しく解説します。
メディアクエリの活用
メディアクエリ(Media Queries)は、CSSの機能の一つで、画面サイズやデバイスの特性に応じて異なるスタイルを適用 できます。
@media (max-width: 600px) {
nav {
display: block;
}
}
このメディアクエリは、画面の幅が600px以下の場合 に適用されます。
@media (max-width: 600px) { ... }
- 画面の幅(
width
)が 600px以下のときに適用 - スマートフォンや小型デバイスを想定
- 画面の幅(
nav { display: block; }
- 通常
nav
はdisplay: flex
やdisplay: inline-block
で横並びになっていることが多い - 小さい画面では
display: block;
に変更することで 縦方向に表示 できる - これにより、メニューが詰まるのを防ぎ、ユーザーが操作しやすくなる
- 通常
/* 大きな画面(デスクトップ向け) */
@media (min-width: 1024px) {
body {
font-size: 18px;
}
}
/* 中程度の画面(タブレット向け) */
@media (max-width: 1023px) and (min-width: 601px) {
body {
font-size: 16px;
}
}
/* 小さな画面(スマートフォン向け) */
@media (max-width: 600px) {
body {
font-size: 14px;
}
}
画面サイズごとに異なるデザインを適用することも可能です。
ビューポートメタタグの設定
<meta name="viewport" content="width=device-width, initial-scale=1.0">
この <meta>
タグは、ページの表示領域(ビューポート)を適切に設定 するためのものです。
各属性の意味:
-
name="viewport"
- ビューポートの設定を行うための指定
-
content="width=device-width"
- デバイスの幅に合わせてページの幅を自動調整 する
- これがないと、PC向けレイアウトがそのまま縮小されてしまい、文字が極端に小さくなったり、横スクロールが発生したりする
-
initial-scale=1.0
- 初期のズーム倍率を1.0(100%)に設定 する
- ユーザーが拡大縮小しない限り、ブラウザが勝手にズームしないようにする
-
ビューポートメタタグを設定しない場合の問題:
- モバイルで閲覧すると、PC向けのデザインがそのまま表示されてしまう
- 文字が小さくなり、拡大しないと読めないことがある
- ユーザーが意図しないスクロールやズームをしないと操作できないことがある
アクセシビリティレポートの定期的な生成
アクセシビリティ(A11y)レポートを定期的に生成することで、Webアプリケーションが常にユーザーにとって使いやすい状態を維持できるようになります。
このプロセスでは、自動テストツールを活用して、アクセシビリティの問題を早期に発見し、改善に役立てます。
axe-core
を使用したアクセシビリティテスト
axe-core
は、Deque Systems によって開発された、業界標準のアクセシビリティテストライブラリです。
React コンポーネントのテストに @testing-library/react
と jest-axe
を使用すると、アクセシビリティ違反を検出できます。
jest-axe のインストール
npm install --save-dev jest-axe @testing-library/react
React コンポーネントのアクセシビリティテスト
import React from "react";
import { render } from "@testing-library/react";
import { axe, toHaveNoViolations } from "jest-axe";
import MyComponent from "../MyComponent";
expect.extend(toHaveNoViolations);
test("MyComponent is accessible", async () => {
const { container } = render(<MyComponent />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
ポイント
axe(container)
: DOM 内のアクセシビリティ違反をチェック。toHaveNoViolations()
: アクセシビリティ違反がないことを確認。
メリット
- コンポーネント単位でアクセシビリティテストを実施できる。
- CI/CD パイプラインに組み込んで、自動的にアクセシビリティをチェックできる。
Lighthouse を CI/CD に組み込む方法
lighthouserc.json
をプロジェクトのルートに配置します。
{
"ci": {
"collect": {
"url": ["https://example.com"],
"numberOfRuns": 3
},
"assert": {
"assertions": {
"categories:accessibility": ["error", { "minScore": 0.9 }]
}
},
"upload": {
"target": "temporary-public-storage"
}
}
}
ポイント
numberOfRuns
: 同じテストを複数回実行し、安定した結果を得るための設定。assertions
: アクセシビリティスコアが 0.9 未満 の場合にエラーを出す。upload
: 結果を一時的なストレージにアップロード。
次にGitHub Actions を使って CI/CD で Lighthouse を実行します。
name: Lighthouse Accessibility Check
on:
schedule:
- cron: '0 0 * * 1' # 毎週月曜日に実行
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- name: リポジトリのチェックアウト
uses: actions/checkout@v4
- name: Lighthouse の実行
run: |
npx lighthouse --config-path=lighthouserc.json
さいごに
Webアクセシビリティの向上は、単なる法令遵守やチェックリストを満たすことではなく、すべてのユーザーにとって快適で公平な体験を提供することが目的です。本記事で紹介したLighthouseやaxeによる自動テストの活用、キーボード操作やスクリーンリーダー対応の改善、ARIAランドマークの導入などを実践することで、アクセシビリティの高いWebサイトを構築できます。
しかし、アクセシビリティ対応は一度設定すれば終わりではなく、継続的な改善が求められます。定期的なレポート生成やユーザーテストを通じて、実際の利用者のフィードバックを取り入れながら改善を続けることが重要です。
すべてのユーザーが快適に利用できるWebを目指して、今日からアクセシビリティ向上に取り組んでいきましょう。
関連する技術ブログ
自動化で業務効率を最大化する方法
定型作業をスクリプトや Bot に置き換え、自動化することで作業時間を削減。データ処理やデプロイ、アラート対応の自動化により、開発生産性を向上させます。
shinagawa-web.com
Playwrightを使ったE2Eテストを実装してシステム間の連携を含めたユーザー視点でのテストを実現
Playwrightを使用したエンドツーエンド(E2E)テストの導入方法から、サンプルコードの実行までを詳しく解説。クロスブラウザテストや並行テスト実行の特徴を活かし、効率的なテスト環境構築を学びましょう。
shinagawa-web.com
フロントエンドテスト戦略の最適解:ユニットテストからE2Eまで徹底強化する方法
est / Vitest を活用したユニットテストの導入、React Testing Library でのコンポーネントテスト最適化、Playwright / Cypress による E2E テストの拡充、API テストの自動化など、開発の品質と効率を向上させるテスト戦略を解説。CI/CD でのテスト実行最適化や、依存関係を考慮したテスト設計、テストカバレッジの可視化、フィーチャーフラグを考慮した戦略まで、実践的なノウハウを詳しく紹介します。
shinagawa-web.com
JestとTypeScriptで始めるテスト自動化:基本設定から型安全なテストの書き方まで徹底解説
JestとTypeScriptを使ったテスト自動化の基本を学びたい方へ。環境のセットアップ方法、型安全なテストを書くメリット、コードの信頼性を高める実践的なテクニックを初心者向けに丁寧に解説します。テストカバレッジの活用で、品質の高い開発を目指しましょう。
shinagawa-web.com
Mock Service Worker (MSW) を使ったAPIモックとテストの効率化
MSW(Mock Service Worker)を使用して、フロントエンド開発やテスト環境でのAPIモックを効率的に行う方法を解説します。Mock Service Workerの基本的な使い方から、Jestテストでの活用方法、さらにテストを簡単にするための設定手順を紹介します。
shinagawa-web.com
フロントエンド開発で欠かせないReactのUIコンポーネントのテストをReact Testing Libraryで実装
React Testing Libraryを使って、Reactコンポーネントのテストを行う方法を学びます。本記事では、Next.js環境でのセットアップから、ユーザーインタラクションをシミュレーションしたテストコードの作成までを詳しく解説します。コンポーネントが期待通りに動作するかを確認し、実際のアプリケーションに近い形でのテストを実装しましょう。
shinagawa-web.com
Supertest と Jest を活用した Express + MongoDB アプリのエンドツーエンドテスト解説
Supertest と Jest を組み合わせて Express アプリケーションの API テストを効率化する方法を解説します。サービス層の導入やテスト可能なコード設計へのリファクタリング、GET, POST, PATCH, DELETEメソッドのテスト実装まで、具体的なコード例を交えて詳しく紹介します。
shinagawa-web.com
JavaScript から TypeScript への移行ガイド
JavaScript から TypeScript への移行は、コードの型安全性を向上させ、バグの早期発見を可能にする重要な取り組みです。本記事では、10の取り組みについて詳しく解説します。
shinagawa-web.com