この技術・考え方で達成できること
- 正確な情報の翻訳: 画面上のUIの見た目(ビジュアル)ではなく、「それが何の役割を持つか(ボタンかリンクか)」を、支援技術を介して機械に正確に伝えられる
- 状態のリアルタイムな通知: メニューが「開いた」や入力が「エラーになった」という視覚的な変化を、バックグラウンドのデータとしても正確に表現できる
- マシンリーダビリティの大幅な向上: スクリーンリーダーだけでなく、検索エンジンのクローラーやAIエージェントにとっても、ページのコンテンツ構造が100%理解可能になる
例: この対応は、画面を見ずに読み上げソフトを使う全盲のユーザー(恒常的な障害)だけでなく、「運転中や家事の最中に、スマートスピーカーやAirPodsの音声アシスタントで記事を読み上げさせている人(状況的な障害)」にとって、情報が意味不明な単語の羅列にならず、論理的な音声UIとして機能するかどうかに直結します。
なぜ対応が難しいか(または後回しにされるか)
ReactやVueなどのモダンなUIフレームワークが普及したことで、**「機能的にはすべて <div> と <span> とJavaScriptで作れてしまう」**という技術的な柔軟性がアダとなっているためです。
セマンティックなHTML(<button>, <nav>, <dialog>)の初期スタイルをリセットするのが手間に感じられるため、見た目の装飾がしやすい <div> にクリックイベントをバインディングする「自作ボタン」が大量に生産されます。
また、WAI-ARIAの仕様が難解に見えるため、アクセシビリティ監査でエラーが出た際、根本のHTMLタグを直すのではなく、「とりあえず role="button" や aria-label を大量に付与してエラーを消滅させる(Bad ARIA)」という強引な対症療法が蔓延しがちです。
実装で取り除ける障壁(バリア)
セマンティクスとWAI-ARIAの実装において、以下のミスマッチ(障壁)を取り除く必要があります。
- 偽物のUIコンポーネント: 視覚的には「美しいボタン」なのに、プログラム上はただの「テキスト(div)」と解釈され、スクリーンリーダーユーザーが「押せる要素」だと気付けない状態。
- 状態のブラックボックス化: パスワード入力の要件を満たしていない際、画面上の枠線は赤くなるが、音声ではエラーであることが一切伝わらない状態。
- ランドマークの欠如: ページの骨格(どこがヘッダーで、どこが本文か)が定まっておらず、ユーザーが常にページの先頭から1行ずつ読み飛ばさなければならない砂漠のような状態。
正しいマークアップパターン(Before/After)
❌ Before: <div> で作られた偽物のボタン
<div class="custom-button btn-primary" onclick="submitForm()">
送信する
</div>
なぜ問題か: 視覚に依存しないユーザーにとって、この要素は「送信する」というただのテキスト文字列です。これが実行可能なアクション(ボタン)であることや、キーボードのEnterキーやSpaceキーで発火できるという機能の恩恵が全て欠落しています。
✅ After: ネイティブHTMLの力(ARIA is no ARIA)
<button type="submit" class="custom-button btn-primary">
送信する
</button>
なぜ改善されるか:
HTMLが元々持っている <button> 要素を使うだけで、ブラウザはこれが「ボタンである(Role)」ことを支援技術に伝え、更に「エンターキーやスペースキーでの発火」や「フォーカス可能な状態」を無料(追加実装なし)で提供してくれます。「HTMLで表現できるなら、WAI-ARIA は使うな」という大原則に従うことが最強のアクセシビリティ対応です。
📌 WAI-ARIAが「本当に必要な」ケース
ネイティブHTMLの能力を超えて、現在の「状態」や「隠された名前」を説明する際のみ、魔法のタグである WAI-ARIA に頼ります。
- アイコンしかない要素の名前 (
aria-label):<button aria-label="メニューを閉じる"><svg>...</svg></button> - 展開・折りたたみの状態 (
aria-expanded):<button aria-expanded="true">詳細オプション</button> - 装飾要素の不可視化 (
aria-hidden):<span aria-hidden="true">➡️</span>(※アイコンなどを読み上げのノイズから消す)
意図の伝達(デザイナー × エンジニア)
❌ アイコンボタンの「名前」の不在
デザイナーの視点: 「このヘッダーの『虫眼鏡アイコン』、見た目だけで検索ボタンだとわかるから、横に『検索』というテキストはダサいので入れたくないです」 エンジニアの視点: 「中にテキストがないボタンは、アクセシビリティツリー上で『名前のないボタン』となり、読み上げソフトで『ボタン』としか読まれません。何のボタンか伝わりません」
なぜ衝突するか: デザイナーが捉える「視覚的な記号(虫眼鏡)」の共通認識が、スクリーンリーダーの世界(テキストベース)に変換されていないからです。
どう合意するか:
「Accessible Name(支援技術向けの隠された名前)」を意図的に設計するというアプローチで合意します。
視覚的なテキストは表示させないまま、エンジニアがコードレベルで <button aria-label="サイト内検索"> を追加するか、または画面外に見えないテキスト(sr-only クラス)を配置することで、「視覚的な美しさ」と「非視覚的な伝達力」を両立させます。
実践チェックリスト
最低ライン(Must)
[ ] 操作可能な要素(リンクやボタン)には、原則としてネイティブの <a> や <button> を使用し、<div> や <span> にクリックイベントをバインドしていない
[ ] テキストを持たないアイコンボタンには、必ず aria-label 属性か .sr-only の非表示テキストで「アクセシブルネーム」を提供している
[ ] 視覚的に隠されている装飾用のアイコンや要素には、aria-hidden="true" を付与して読み上げのノイズにならないようにしている
理想ライン(Better)
[ ] <header>, <main>, <nav>, <footer> などのランドマークを利用してページの骨格をマークアップし、スクリーンリーダーのジャンプ機能に対応している
[ ] トグルボタンやアコーディオンを展開する際、aria-expanded 属性を JavaScript と連動させて動的に true/false を切り替え、状態の変化を伝えている
[ ] role 属性や WAI-ARIA を「とりあえず」で多用していない(WAI-ARIA の第1のルール:ARIA を使わないことに越したことはない)
まとめ
- この記事の本質: セマンティクスは「ブラウザへの仕様書」であり、正しく書けばアクセシビリティの8割は自動的に満たされる。
- 誰のどんな課題を解決するか: 画面を見ずに操作するユーザーや音声アシスタント利用者の、「謎のボタン」や「謎のテキスト」による絶望感。
- 実務での判断軸: 「画面のCSSをすべて剝がしたとき、このHTMLだけで情報としての意味や役割は成り立つだろうか?」
- 次に学ぶべき知識: スクリーンリーダーUX(視覚に頼らないユーザーがどう情報を脳内にマッピングしているかの疑似体験)
目的別のおすすめ:
- WAI-ARIAを付与する前にフォーカスの動きを正すなら → キーボードナビゲーション
- WAI-ARIAを乱用しない美しいUIコンポーネント集なら → UIXHEROのコンポーネント実装