セマンティックHTMLとARIAで誰でも迷わないUIを設計!axe検証の導入
Webサイトを作ったものの、Tabキーを押すとどこにフォーカスがあるか分からない、スクリーンリーダーで読み上げると意味不明になる、といった問題を後回しにしていませんか。「どのタグを選べばいいのか」「WAI-ARIAはいつ使うのか」で手が止まる方は多いです。この記事では、Webアクセシビリティの基本を セマンティックHTML、キーボード操作、WAI-ARIA、自動検証 の4点に絞り、コード例つきで整理します。フロントエンド入門の段階から、今日の実装で試せる内容です。
なぜ今アクセシビリティが重要なのか?誰にとっても使いやすいWebの基本
Webアクセシビリティとは、障害の有無や利用環境にかかわらず、情報や機能を使えるようにすることです。対象は視覚や聴覚、運動機能に障害がある方だけではありません。怪我で片手がふさがっている状況、屋外の強い日差しで画面が見にくい状況、マウスのないキーボード中心の環境も含みます。つまり、誰もが状況次第で当事者になります。
制度面の動きもあります。日本では、改正障害者差別解消法が2024年4月に施行され、民間事業者にも合理的配慮の提供が義務化されました。欧州では、European Accessibility Act に基づく要件が2025年6月から適用されています。サービスの提供先によっては、対応が事業上の前提になりつつあります。
具体的な達成基準を知りたいときは、W3Cが勧告している WCAG (Web Content Accessibility Guidelines) が基準になります。2023年10月にWCAG 2.2が勧告となり、日本の JIS X 8341-3 も WCAG 2.0 と対応しています。ただし、最初から全基準を読み込む必要はありません。まずは「正しいHTMLを書く」「キーボードで操作できる」の2点を押さえるだけで、多くの問題を避けられます。
まずはセマンティックHTMLから!「divだらけ」を脱却して意味のあるマークアップへ
セマンティックHTMLとは、見た目ではなく意味に合ったタグを選ぶ書き方です。ブラウザは button や nav といった要素に対して、役割やキーボード操作、フォーカス挙動を標準で提供します。支援技術もその情報を読み取ります。div と span にはこうした意味がないため、同じ機能を自作すると実装量が増え、抜け漏れも起きやすくなります。
次の2つを比べてみましょう。
<!-- 避けたい例 -->
<div class="btn" onclick="save()">保存</div>
<!-- 推奨 -->
<button type="button" onclick="save()">保存</button>
div 版はTabキーでフォーカスが当たらず、EnterキーやSpaceキーでも動きません。スクリーンリーダーも「ボタン」と伝えません。button 版は、これらをすべて標準で満たします。
ページ全体の構造も同様です。header、nav、main、footer などを使うと、スクリーンリーダー利用者はランドマーク機能で目的の領域へ直接移動できます。見出しは h1 から順に、階層を飛ばさず使ってください。見出しの一覧から内容を把握する利用者が多いためです。
<header>…</header>
<nav aria-label="メインメニュー">…</nav>
<main>
<h1>記事タイトル</h1>
<section>
<h2>見出し</h2>
</section>
</main>
<footer>…</footer>
画像には alt 属性が必要です。内容を伝える画像には説明文を、装飾目的の画像には alt="" を指定すると、読み上げ対象から外れます。フォームでは label 要素を for と id で入力欄に関連付けてください。placeholder だけでは、入力を始めるとヒントが消えるため、ラベルの代わりになりません。
キーボードだけで操作できる?フォーカス移動とtabindexの正しい扱い方
試しにマウスを置いて、Tab、Shift+Tab、Enter、Spaceだけで自分のサイトを操作してみてください。これだけで多くの問題が見つかります。確認する点は3つです。すべての操作ができること、フォーカス位置が見えること、移動順が画面の読み順と一致していることです。
セマンティックHTMLを使えば、a、button、input などは最初からフォーカス可能です。tabindex は「例外的に」使う属性として、次の値だけ覚えれば十分です。
tabindex="0": 通常のタブ順にフォーカス可能として加えます。tabindex="-1": Tabでは止まりませんが、JavaScriptのfocus()で移動できます。モーダル表示後などに使います。tabindex="1"以上: 使わないでください。タブ順が DOM の並びと食い違い、保守も難しくなります。
注意したいのが、CSSで outline: none と書いてフォーカスの枠線を消してしまう実装です。フォーカス位置が見えなくなり、キーボード利用者は迷子になります。消すのではなく、見やすく整えましょう。
:focus-visible {
outline: 3px solid #1a5fd0;
outline-offset: 2px;
}
:focus-visible は、キーボード操作時を中心にフォーカスリングを表示する疑似クラスで、主要なブラウザで利用できます。また、長いナビゲーションがあるページでは、先頭に「本文へスキップ」リンクを置くと、キーボード利用者が毎回の Tab 移動を省けます。ダイアログは dialog 要素を使うと、フォーカス管理の一部をブラウザに任せられます。
WAI-ARIAの第1原則:安易に使わない!必要な場面と代表的な属性(aria-label, roleなど)
WAI-ARIAは、HTMLだけでは表現できない役割や状態を支援技術に伝える仕様です。W3Cの「Using ARIA」には、ARIA利用の第1原則として「ネイティブのHTML要素で目的を満たせるなら、ARIAを使わない」と書かれています。ARIAは見た目も動作も変えません。伝えるのは情報だけで、キーボード操作は自分で実装しなければなりません。誤って付けると、何も付けないより悪い体験になることもあります。
それでも必要になる場面はあります。代表的な属性を押さえましょう。
aria-label: 見える文字がない要素に名前を与えます。アイコンのみのボタンが典型です。aria-expanded: 開閉できる要素の現在の状態を伝えます。aria-describedby: 入力欄とエラーメッセージなど、補足説明を関連付けます。aria-live: 画面の一部が動的に更新されたときに、読み上げで通知します。role: ネイティブ要素で表現できない役割を指定します。
<button type="button" aria-label="メニューを閉じる">
<svg aria-hidden="true">…</svg>
</button>
<button type="button" aria-expanded="false" aria-controls="faq1">
よくある質問
</button>
<div id="faq1" hidden>…</div>
2つ目のボタンは、クリックで aria-expanded を true に切り替え、同時に hidden を外す処理を自分で書く必要があります。状態の更新を忘れると、画面と読み上げの内容がずれます。また、<button role="link"> のように、既存の意味を上書きする使い方は避けてください。迷ったときは、まず MDN や W3C の ARIA Authoring Practices Guide (APG) で、同じ部品の実装例を確認すると安心です。
開発フローに組み込む!axeやLighthouseを活用したアクセシビリティ検証の実践
アクセシビリティは、リリース前にまとめて確認すると手戻りが大きくなります。日常の開発に小さな検証を組み込むのが効果的です。入り口として手軽なのが、Chrome DevTools の Lighthouse です。「Accessibility」カテゴリにチェックを入れて実行すると、コントラスト不足、alt の欠落、ラベルのない入力欄などを一覧できます。Lighthouse のアクセシビリティ検査は、Deque が公開するオープンソースのエンジン axe-core をもとにしています。
さらに継続的に確認するなら、テストコードに axe-core を組み込めます。たとえば Playwright なら、次のように書けます。
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('トップページに検出可能な違反がない', async ({ page }) => {
await page.goto('http://localhost:3000/');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});
これをCIで実行すれば、プルリクエストの段階で退行に気づけます。チーム開発では「新しい画面は検証を通す」というルールにしておくと、保守性が大きく上がります。
ただし、自動検証で見つかるのは問題の一部です。「alt の内容が適切か」「フォーカス順が自然か」といった判断は、人の目と手が必要です。自動検査に加えて、キーボードだけでの操作確認と、スクリーンリーダー(NVDA、VoiceOver など)での読み上げ確認を、主要な画面で定期的に行ってください。この3つを組み合わせると、無理なく品質を保てます。


