ARIA
ARIA(Accessible Rich Internet Applications)は、HTML だけでは表現できない意味付けを補うための属性群。 強力だが、誤用すると「a11y を悪化させる」道具にもなる。
5 つのルール(W3C)
1. ARIA を使わなくて済むなら使わない
ネイティブの HTML 要素で同じ意味が表現できるなら、それを使う。
「div + ARIA」より「適切な HTML 要素」のほうが常に良い。
<!-- BAD -->
<div role="button" tabindex="0" onclick="...">送信</div>
<!-- GOOD -->
<button type="button" onclick="...">送信</button>
2. ネイティブのセマンティクスを変えない
<h1 role="button"> のように、本来の意味を上書きしない。スクリーンリーダの利用者が混乱する。
3. すべてのインタラクティブ ARIA 要素はキーボードで操作可能
role="button" を付けたら、Tab で来る・Enter / Space で発火するように JS で実装する必要がある。
<button> ならこれが全部タダ。
4. role="presentation" / aria-hidden="true" をフォーカス可能要素に付けない
フォーカスは入るのにスクリーンリーダから見えない、という最悪の状態になる。
5. インタラクティブ要素はアクセシブルな名前を持たなければならない
ボタン・リンク・入力欄には必ず「何のもの」かの名前が必要。
<label>、aria-label、aria-labelledby、内部テキストのいずれかで。
3つのカテゴリ
1. role — 種別
要素が「何の種類のもの」かを表す。HTML タグの暗黙の role を上書き、または div/span に追加する。
<div role="alert">エラーが発生しました</div>
<ul role="tablist"> ... </ul>
2. aria-*(プロパティ) — 静的な属性
要素についての「変わらない情報」。
aria-label— アクセシブルな名前を直接付けるaria-labelledby— 別要素の id を参照して名前にするaria-describedby— 補足説明として参照aria-controls— どの要素を制御するか(コンボボックス等)aria-haspopup— クリックでポップアップが開く
3. aria-*(ステート) — 動的な状態
要素の「現在の状態」。JS で値を更新する。
aria-expanded— 展開中か(true/false)aria-pressed— トグルボタンの押下状態aria-checked— チェック状態aria-selected— 選択状態aria-disabled— 無効状態(disabledと違って Tab で来る)aria-current— 現在地("page" / "step" / "location" 等)aria-invalid— エラー状態aria-busy— 読み込み中aria-hidden— SR から隠す
名前の付け方(accessible name)
要素の「名前」は以下の優先順位で決まる:
aria-labelledbyaria-label- 関連付けされた
<label>(input の場合) - 要素の内部テキスト(button の場合)
title属性(最後の手段)
典型例
<!-- アイコンのみのボタン -->
<button aria-label="削除">
<svg aria-hidden="true">...</svg>
</button>
<!-- 入力欄 -->
<label for="name">氏名</label>
<input id="name" />
<!-- 検索フォーム(label を出したくない場合) -->
<input type="search" aria-label="検索" />
<!-- 別要素を参照 -->
<h2 id="dialog-title">確認</h2>
<div role="dialog" aria-labelledby="dialog-title"> ... </div>
aria-label の使いすぎに注意
aria-label は視覚に出ないテキスト。視覚的なラベルが既にあるならそちらを使う方がいい
(音声入力で「○○ボタンを押して」と言える等の利点がある)。
視覚ラベルと aria-label が違うと、音声入力ユーザーが「見えるラベルで言ったのに反応しない」事態になる。
よく使う role と用途
ランドマーク
基本は HTML 5 タグで自動付与される。<main> = main、<nav> = navigation 等。
div しか使えない歴史的な事情があるなら role で代替。
ライブリージョン
| role | 用途 |
|---|---|
role="alert" | 緊急の通知(赤いエラー等)。即座に読み上げ。 |
role="status" | 状態通知("保存しました" 等)。控えめに読み上げ。 |
role="log" | 追加され続けるログ(チャットメッセージ)。 |
role="timer" | タイマー表示。 |
ダイアログ系
role="dialog"— モーダル/非モーダルダイアログrole="alertdialog"— 緊急のダイアログ
タブ・メニュー
role="tablist"/role="tab"/role="tabpanel"role="menu"/role="menuitem"/role="menubar"
選択系
role="combobox"+role="listbox"+role="option"role="radiogroup"+role="radio"
典型的な実装パターン
展開ボタン(アコーディオン・dropdown)
<button
type="button"
aria-expanded="false"
aria-controls="panel-1"
>
詳細を表示
</button>
<div id="panel-1" hidden>
... 中身 ...
</div>
クリックで aria-expanded を切り替え、hidden 属性を付け外し。
トグルボタン
<button type="button" aria-pressed="false">
サイレント
</button>
押されたら aria-pressed="true" に。SR は「押されています、サイレント、ボタン」と読み上げる。
現在地(パンくず・ナビ)
<nav aria-label="グローバル">
<ul>
<li><a href="/">ホーム</a></li>
<li><a href="/a11y/" aria-current="page">a11y</a></li>
</ul>
</nav>
モーダルダイアログ
<!-- ネイティブ
エラーアラート
<div role="alert">
メールアドレスの形式が正しくありません
</div>
動的な状況通知(ステータス)
<div role="status" aria-live="polite">
3 件のメッセージを保存しました
</div>
aria-hidden の使い方
要素をスクリーンリーダから隠す。視覚的には見えるが SR から無視される。
- 装飾用のアイコンや絵文字に
- 視覚ラベルと別の SR 用テキストがある場合の重複防止
- モーダル背景に(ただし最近は
inertの方が良い)
aria-hidden は禁忌
aria-hidden="true" を付けた要素の中にボタンや input があると、Tab で来るのに
SR では読まれない最悪の状態。実装中によくある事故。
「視覚的に隠すが SR には見せる」
スクリーンリーダ専用テキストを入れたい時の定番 CSS。display: none や
visibility: hidden は SR からも消えるのでダメ。
.sr-only {
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="sr-only">削除</span>
</button>
避けるべきアンチパターン
- 意味のない role 連打(
role="button"を<button>に書く等) role="presentation"をフォーカス可能要素にaria-labelで視覚ラベルと違う名前を付ける(音声入力ユーザー混乱)- 無関係な要素の
aria-hidden(中にボタンがあると死ぬ) - 複数の見出しに
aria-hidden(SR利用者は見出しを使う) - 意味なく
tabindex="0"(Tab 順を増やすだけ) - すべての画像に
role="img"(<img>はもとからそう)
判断フロー
- そのまま HTML タグで意味が出るか? → 出るなら何もしない
- 視覚ラベルがない/不十分か? →
aria-labelまたはaria-labelledby - 状態を伝えたい? →
aria-expanded/aria-pressed/aria-current - 動的な情報を通知したい? →
role="status"/role="alert"/aria-live - カスタムウィジェットを作る? → APG をコピペ
W3C 公式のUI パターン集。タブ、メニュー、ツリービュー、ダイアログ、コンボボックス等の
実装方法(HTML + ARIA + キーボード操作)が体系的にまとまっている。
https://www.w3.org/WAI/ARIA/apg/
自前で凝った UI を作るときは、必ず該当パターンの実装例を確認する。