HTML
この記事では、画面には表示したまま、スクリーンリーダーなどの支援技術から要素を除外するaria-hidden属性と、フォーカス可能な要素へ誤用しないための注意点を初心者向けに説明します。
この記事でわかること
- 装飾的なコンテンツを支援技術から除外する方法
- 利用者に必要な情報を隠してはいけない理由
- フォーカス可能な要素に
aria-hiddenを付けてはいけない理由
The aria-hidden attribute is a declaration that keeps an element and its descendants visible on-screen while hiding them from assistive technologies like screen readers so they aren’t announced.
aria-hidden 属性
- 何のための aria-hidden か
- 基本構文と値
- 仕組みを理解する:アクセシビリティツリーとの関係
- 典型的な利用シーン
- コード例:良い実装と悪い実装
- ダイアログやモーダルでの動的切替
- aria-hidden と CSS の違い
- ベストプラクティスまとめ
- よくある質問 (FAQ)
- まとめ
何のための aria-hidden か
Web ページは「見た目の DOM」と「支援技術がたどるアクセシビリティツリー (A11y ツリー)」という 2 つの“世界” を持っています。aria-hidden は後者に送るシグナル――
「この要素と子孫は A11y ツリーに載せるべきではない」
という宣言です。アイコンのような装飾や、折りたたみ中のパネルなど 視覚上は存在するが読まれたくない ノードを排除し、スクリーンリーダー利用者が目的の情報に素早くたどり着ける体験を実現します。
基本構文と値
HTML
<!-- 非表示にしたい要素 -->
<span aria-hidden="true">★</span>
<!-- 必ず見せたい場合(既定値) -->
<span aria-hidden="false">テキスト</span>
true…自身と子孫を A11y ツリーから完全に除外false…明示的に“非除外”を宣言(省略可)- 省略時は UA(ブラウザ)が適切に判定します。
注意 : aria-hidden は 視覚的な非表示 を行いません。レイアウトから要素を取り除きたいときは display:none など CSS と併用します。
仕組みを理解する:アクセシビリティツリーとの関係
- ブラウザは DOM を解析して セマンティック情報(タグ名・役割・名前など)を抽出
- これを OS 提供の Accessibility API へ登録 → スクリーンリーダーが読み上げ
aria-hidden="true"がある要素は この登録をスキップ する- 結果として視覚的には存在していても ユーザー補助技術から“消える”
典型的な利用シーン
| シーン | 具体例 | なぜ必要か |
|---|---|---|
| 装飾アイコン | ♻︎, ソーシャルアイコン | 「リサイクルマーク」など不要な読み上げを抑制 |
| 重複テキスト | 視覚的に省略するための <span> |
同じ語句が二重に読まれるのを防ぐ |
| 折りたたみメニュー・アコーディオン | 非表示中の li 群 |
フォーカス移動で“見えない項目”に迷い込むのを防止 |
| スクロールスナップ用オフスクリーン要素 | ガイド用ダミー要素 | 実際の内容ではないため読み上げ不要 |
コード例:良い実装と悪い実装
⭕ 良い実装(装飾アイコン)
HTML
<button class="btn-delete">
<svg aria-hidden="true" focusable="false">…</svg>
<span class="visually-hidden">Delete</span>
</button>
アイコンは隠し、読み上げに必要なラベルを別途提供。
❌ 悪い実装(フォーカス要素を隠す)
HTML
<div aria-hidden="true">
<a href="#next">次へ</a>
</div>
a 要素は フォーカス可能。aria-hidden で隠すと キーボード操作が不能 になり、WCAG 失格。フォーカス可能要素を子孫に含めない のが原則です。
ダイアログやモーダルでの動的切替
JavaScript
const dialog = document.querySelector('#dialog');
const main = document.querySelector('main');
function openDialog(){
dialog.removeAttribute('aria-hidden'); // 表示
main.setAttribute('aria-hidden','true'); // 背景をツリーから除外
dialog.querySelector('[autofocus]').focus();
}
function closeDialog(){
dialog.setAttribute('aria-hidden','true');
main.removeAttribute('aria-hidden');
}
背景を aria-hidden にしないと スクリーンリーダーが裏のコンテンツも読む
ただし近年は inert 属性 がほぼ同じ目的をブラウザ標準で達成可能。モーダル内のフォーカストラップまで自動化できるため、最新ブラウザでは inert が推奨されつつあります。
aria-hidden と CSS の違い
| 目的 | aria-hidden | display:none / visibility:hidden |
|---|---|---|
| 視覚に表示 | 変化なし | 非表示(レイアウト外 / 透明) |
| A11y ツリー | 除外 | 除外 (display:none の場合) |
| フォーカス | DOM に残る要素は取得可能 | 不可 (display:none) |
| アニメーション前後で使い分け | ◎ | △(display 切替は再フローが発生) |
ベストプラクティスまとめ
- 装飾・重複・無効状態 など 読み上げ不要 な場面で使う
- フォーカス可能要素を含めない
- 視覚的にも非表示にしたい場合は CSS を併用
- 状態変化(モーダル開閉など)は JS で属性を動的に付け外し
- 同じ目的で
inertを使えるならinertを第一候補 に - 静的サイトジェネレーター等で誤って本文全体に付与しないよう lint を活用
- 必ずテスト: NVDA/JAWS/VoiceOver + 自動ツール (axe, Lighthouse, ACT ルール)
よくある質問 (FAQ)
aria-hidden="false"を書く意味は?- 子要素に
falseを付けても、親のtrueは打ち消せません。親の設定を見直す必要があるため、通常は省略で問題ありません。 - SEO に影響する?
- 検索エンジンは A11y ツリーではなく DOM を解析。表示されていればインデックス対象。ただし装飾アイコン等は検索順位に無関係。
- CSS だけで隠せば十分では?
- 非表示中でもアニメーション前・画面外に存在する要素を「読み上げさせたくない」場合は
aria-hiddenが必要。
まとめ
aria-hidden は「見えているが読まれなくてよい要素」を選別し、A11y ツリーを最適化する強力なツールです。ただし フォーカス管理と誤用 に注意し、可能なら inert など新しい仕組みを組み合わせることで、より堅牢かつメンテナンスしやすいアクセシブル UI を実装できます。