本文へ移動
easeweb
ご相談

HTMLとARIAから、スクリーンリーダーに何が伝わるか

ブラウザーがHTMLとARIAからアクセシビリティツリーを作る仕組みと、そこに入るロール、名前、説明、状態がそれぞれどこから来るか

要点:ブラウザーはDOMからアクセシビリティツリーを作ります。ページの各部分が、ロール、名前、説明、状態、関係を持つオブジェクトになり、OSのアクセシビリティAPIを通じてスクリーンリーダーに渡ります。HTMLはそれだけでツリーを満たします。ARIAはツリーに入る内容を変えられますが、ページの動作は変えません。

01

使う場面

再現した設定画面について、テスト担当者から3行のメモが届きます。

  • ゴミ箱のアイコンは「ボタン」としか読まれない。
  • 「メール通知」はただの文字として読まれる。切り替えられることも、オンかどうかも伝わらない。
  • 表示名の欄の下にある「プロフィールに表示されます」というヒントが読まれない。

画面ではどれも正しく見え、聞こえなかった言葉もすべてコードに書いてあります。スクリーンリーダーはコードを読むのではなく、ブラウザーから渡された情報を読みます。この記事は、その渡される情報についての話です。

02

DOMからスクリーンリーダーまで

利用者が聞く内容は、4つの層を通って届きます。

  1. DOM: HTMLとスクリプトが作る要素と属性です。
  2. アクセシビリティツリー: AccName 1.1の1章は「ユーザーエージェントはDOMから情報を取得し、アクセシブルなオブジェクトからなるアクセシビリティツリーという並行した構造を作る」と説明しています。
  3. プラットフォームのアクセシビリティAPI: ブラウザーは各オブジェクトをOSのアクセシビリティAPIで公開し、変化があればイベントで知らせます。
  4. 支援技術: スクリーンリーダー、音声操作、画面拡大ソフトなどがAPIに内容と変化を問い合わせ、音声や点字、コマンドに変えます。

ブラウザーが対応させるAPIは、Core Accessibility API Mappings(Core-AAM)1.2の1.1節に挙げられています。

プラットフォーム アクセシビリティAPI
Windows MSAAとIAccessible2、UI Automation
macOS macOS Accessibility Protocol(AX API)
Linux ATKとAT-SPI
Android Androidのアクセシビリティ API

この一覧にiOSはありません。どのAPIに渡る場合も、ツリーの各オブジェクトが持つ情報の種類は同じです。

情報 例 元になるもの
ロール button、checkbox、link 要素そのもの、または role 属性
名前 「下書きを削除」 中身、label、alt、aria-label、aria-labelledby
説明 「プロフィールに表示されます」 aria-describedby、名前に使われていない title
状態とプロパティ(値を含む) チェック済み、展開、無効、スライダーの値 要素自身の状態、または aria-* 属性
関係 ラベル付け、制御、所有、親子 label for、aria-labelledby、aria-controls、aria-owns、入れ子

ツリーに届かない内容もあります。WAI-ARIA 1.2は、要素かその祖先が描画されていない(display: none)か、aria-hidden="true" を持つ場合に、その要素を隠れているものとして扱います。AccName 1.2は visibility: hidden も隠れているものに含めています。opacity: 0 の文字や画面外へ移した文字は隠れておらず、ブラウザーはツリーに残します。そのため、aria-hidden のリンクの中のバッジはリンクと一緒にツリーから消えます(画面に見えるのにスクリーンリーダーが読まないテキスト)。一方、画面外へ移して aria-hidden で隠したリンクには、フォーカスが移ってしまいます(Tabで届くのに読み上げられない、aria-hiddenの要素)。

03

ロール:HTMLが決めるもの、ARIAが変えるもの

HTMLの要素にはそれぞれ暗黙のロールがあります。role 属性がないときに対応するロールで、HTML Accessibility API Mappings(HTML-AAM)の3.5節が定めています。

要素 暗黙のロール
<button> button
<a href="…"> link
href のない <a> generic
<input type="checkbox"> checkbox(チェックの状態も伝わる)
<nav> navigation
<section> アクセシブル名があればregion、なければgeneric
<div>、<span> generic

role 属性は暗黙のロールを置き換えます。WAI-ARIA 1.2の1.1節によれば、ARIAのロールを付けた要素は、HTMLから受け継ぐ意味にかかわらず、そのウィジェットや構造として扱われます。WAI-ARIA 1.2の5.3節は、ロールを6つに分類しています。

分類 ロールの例 作成者にとっての意味
抽象ロール command、composite、input、landmark、range、roletype、section、sectionhead、select、structure、widget、window 「作成者は抽象ロールをコンテンツに使ってはならない(MUST NOT)」。体系を作るためだけにある
ウィジェット button、checkbox、option、slider、switch、tab、textbox。複合ウィジェットのcombobox、grid、listbox、menu、radiogroup、tablist、tree 操作できる部品。キー操作と動作はページが用意する
文書構造 article、generic、heading、img、list、none、table、toolbar、tooltip 内容を整理する。通常は操作しない
ランドマーク banner、complementary、contentinfo、form、main、navigation、region、search 移動の目印になる領域
ライブリージョン alert、log、marquee、status、timer 変化が読み上げられる内容
ウィンドウ alertdialog、dialog ページの中のウィンドウ

aria-* 属性は、ステートとプロパティに分かれます。WAI-ARIA 1.2の6.1節によれば、aria-labelledby のようなプロパティは、aria-checked のように操作でよく変わるステートより、値が変わりにくいものです。ただし、これは決まりではなく、aria-valuetext のように頻繁に変わるプロパティもあるとしています。仕様書では、両方をまとめて「属性」と呼ぶことがほとんどです。

どれも、要素の動作は変えません。WAI-ARIA 1.2の1.3節は、ARIAはアクセシビリティAPIに公開する内容を改善するだけで、それ以外はユーザーエージェントは本来どおりに動作すると説明しています。たとえば次のコードです。

<div role="button">変更を保存</div>

ツリーには「変更を保存」という名前のボタンが入ります。それでも div にはフォーカスが移らず、EnterキーもSpaceキーも効きません。フォーカスとキー操作は、要素と tabindex、スクリプトが決めるもので、ARIAが決めるものではないためです。続きは「Tabキーで到達できないdivのボタン」で説明しています。

04

ARIAを使うときのルール

W3CのUsing ARIAは、HTMLでARIAを使うときのルールをまとめた文書です。最後の草案(2018年9月27日)にはルールが5つありました。2026年2月24日、W3Cはこの文書を作業中止の草案として公開しました。ルールは「経緯を残し、参照しやすくするため」4つが残され、それ以上の指針はARIA Authoring Practices Guideを参照するよう書かれています。もともと参考情報で、要件ではありません。

ルール 内容 例
1 必要な意味と動作を備えたHTML標準の要素や属性があれば、別の要素にARIAを足さずにそれを使う Tabキーで到達できないdivのボタン
2 どうしても必要な場合以外は、HTML標準の意味を変えない。<h2 role="tab"> ではなく <div role="tab"><h2>…</h2></div> と書く Using ARIA自身の例。ただしWAI-ARIA 1.2ではtabの子孫は表示のためだけのもの(5.2.9節)で、ブラウザーはh2を見出しとして公開しないことになっている
3 ARIAで作った操作部品は、すべてキーボードで使えるようにする ウィジェットの中の矢印キー:roving tabindexとaria-activedescendant
4 フォーカス可能な要素に role="presentation" や aria-hidden="true" を使わない Tabで届くのに読み上げられない、aria-hiddenの要素
5(2018年の草案のみ) 操作できる要素には、すべてアクセシブル名を付ける 名前がないアイコンだけのボタン

5つ目のルールは作業中止の版にはありません。ただし、求められていること自体は変わらず、WCAG 2.2の達成基準4.1.2が、すべてのユーザーインターフェイスコンポーネントに名前を求めています。

05

名前と説明はどこから来るか

ブラウザーは、Accessible Name and Description Computation(AccName)に従ってアクセシブル名を決めます。W3C勧告は1.1(2018年12月18日)で、1.2はこの記事の日付の時点で草案(2026年10月21日)です。どちらも次の順に調べ、最初に名前が得られたところで決まります(AccName 1.1の4.3節。ラベルの中に埋め込まれたコントロールの手順は省いています)。

  1. 隠れた要素: 名前になりません。aria-labelledby、aria-describedby、label から直接指されている場合は別です。
  2. aria-labelledby: 指している要素の文字を、書いた順につなげます。ページにないidは飛ばされます。「読み上げを誤らせる、無効なARIA」はこの例です。
  3. aria-label: その値です。要素の中の文字に代わって名前になります。ボタンに「かごに入れる」と表示しながら別の名前にできてしまうのはこのためで、「表示と名前が食い違うボタンとリンク」で説明しています。
  4. 要素自身のラベル: label 要素、alt、表の caption などです。
  5. 中身: button、link、checkbox、option、tabなど、中身から名前を得るロールでは、中の文字を子要素ごとに、CSSの ::before と ::after の文字も含めて集めます。titleのないSVGしかないボタンでは何も得られません(名前がないアイコンだけのボタン)。
  6. ツールチップ: title です。ほかのどれからも名前が得られなかったときだけ使います。

HTML-AAMの4.1節は、要素ごとにこの中の順番を定めています。テキストの入力欄では、aria-labelledby か aria-label、label、title、placeholder の順です。button では、aria-labelledby か aria-label、label、中身、title の順です。img では、aria-labelledby か aria-label、alt、title の順です。

名前を付けられないロールもあります。WAI-ARIA 1.2の5.2.8.6節にgenericやparagraphなどが挙げられ、AccName 1.2は、作成者がそれらに aria-label や aria-labelledby を使ってはならない(MUST NOT)としています。普通の span に付けた aria-label がスクリーンリーダーに届かないことがあるのはこのためで、「読み上げられないことが多い、divやspanのaria-label」で説明しています。

アクセシブルな説明は、名前とは別のプロパティです。AccName 1.1の4.2節では、aria-describedby が指す要素から作ります。草案のAccName 1.2とHTML-AAMの4.2節は、もう少し詳しい順番を示しています。aria-describedby、aria-description、名前に使われていない表の caption などの要素、名前に使われていない title の順です。aria-description はWAI-ARIA 1.2にはありません。説明をいつ読むかはスクリーンリーダーごとの対応の問題で、ツリーの問題ではありません。組み合わせごとの確認はスクリーンリーダーの対応状況にまとめています。名前を付ける属性の違いは、名前と説明の比較にまとめています。

06

開発者ツールでツリーを読む

次の2つのブラウザーでは、ページから作ったアクセシビリティツリーを見られます。Firefoxのインスペクターが示すのはFirefox自身のツリーで、どのプラットフォームでも同じです。プラットフォームのAPIに渡った形ではありません。

  • Chrome: Elementsパネルで要素を選び、Accessibilityタブを開きます(ボタン名などは英語版の表示です。タブはMore Tabsボタンの奥にあることもあります)。ツリーの中での位置、ARIA Attributes、Computed Propertiesが表示されます。Show accessibility treeをオンにすると、DOMツリーの代わりにページ全体のアクセシビリティツリーが表示されます。
  • Firefox: 開発ツールのAccessibilityタブを開くか、ページを右クリックしてInspect Accessibility Propertiesを選びます(英語版の表示です)。左のパネルに各オブジェクトのロールと名前が並び、右のパネルに名前、ロール、操作、値、説明、状態、関係などが表示されます。Check for issuesでは、Contrast、Keyboard、Text Labelsの問題だけに絞り込めます。Show Tabbing Orderをオンにすると、フォーカス可能な要素に番号が付きます。

ロールの呼び方はブラウザーによって違い、Firefoxではボタンが「pushbutton」と表示されます。コントロールごとにロール、名前、説明、状態を読み、画面の表示と合っているか確かめます。ツリーで分かるのは情報があるかどうかまでです。スクリーンリーダーがそれをどう読むかは、製品、モード、バージョンによります。ほかの確認方法は「無料のアクセシビリティツール」にあります。

07

実例

テスト担当者のメモにあった設定画面は、次のように作られていました。

<div class="toggle on" onclick="toggleAlerts()">メール通知</div>

<button class="icon-button" onclick="deleteDraft()">
  <svg class="icon">
    <use href="#bin"></use>
  </svg>
</button>

<input id="display-name" placeholder="表示名">
<p class="hint">プロフィールに表示されます</p>

開発者ツールで各コントロールを読み、直した結果です。

コントロール 修正前のツリー 修正後のツリー
メール通知 名前を付けられないgenericの div。言葉はただの文字で、状態もフォーカスもない 「メール通知」という名前の、チェック済みのチェックボックス
ゴミ箱アイコン 名前のないボタン。SVGにtitleがなく、中身から名前が得られない 「下書きを削除」という名前のボタン
表示名 placeholderから「表示名」という名前が付いた入力欄。説明はない ラベルから「表示名」という名前が付き、「プロフィールに表示されます」という説明を持つ入力欄

修正後のコードです。

<input type="checkbox" id="alerts" checked>
<label for="alerts">メール通知</label>

<button type="button" aria-label="下書きを削除" onclick="deleteDraft()">
  <svg class="icon" aria-hidden="true">
    <use href="#bin"></use>
  </svg>
</button>

<label for="display-name">表示名</label>
<input id="display-name" aria-describedby="display-name-hint">
<p id="display-name-hint">プロフィールに表示されます</p>

切り替えはHTML標準のチェックボックスにしたので、ロールも状態もキー操作もブラウザーが用意します(ルール1)。ゴミ箱のボタンには名前を付け、アイコンはツリーから外しました。入力欄には見えるラベルを付けたので、それが名前になり、入力を始めると画面から消えるplaceholderに頼らなくなりました。ヒントは説明になりました。もう一度ツリーを読むと、どのコントロールにも、テスト担当者が期待したロール、名前、状態、説明があります。その後、実際にどう聞こえるかをスクリーンリーダーで確かめます。

08

よくある間違い

  • ロールを付けて終わりにする。 role="button" でツリーにはボタンが入りますが、ARIAが変えるのはツリーだけなので、Tabキーでも他のキーでも操作できないままです。「Tabキーで到達できないdivのボタン」を参照してください。
  • div や span に aria-label で名前を付ける。 genericは名前を付けられないロールなので、その言葉がスクリーンリーダーに届かないことがあります。「読み上げられないことが多い、divやspanのaria-label」を参照してください。
  • フォーカスが届く要素に aria-hidden="true" を付ける。 ツリーからは消えてもTabの移動先には残るため、スクリーンリーダーが名前を伝えられない場所にフォーカスが移ります。「Tabで届くのに読み上げられない、aria-hiddenの要素」を参照してください。
  • ページにないidを aria-labelledby で指す、または aria-role と書く。 ブラウザーはたどれない参照も知らない属性も無視しますが、コードは正しく見えたままです。「読み上げを誤らせる、無効なARIA」を参照してください。
  • 見えている言葉を含まない aria-label を付ける。 名前を決める順番で中身より先に使われるため、ボタンに表示された言葉が名前から消えます。「表示と名前が食い違うボタンとリンク」を参照してください。
  • 文字のないアイコンだけにする。 ボタンでは title の前に残る手がかりは中身だけですが、titleのないSVGからは何も得られません。「名前がないアイコンだけのボタン」を参照してください。
  • 隠した要素の中に情報を置く。 aria-hidden="true" の中にあるものは、すべて一緒にツリーから消えます。「画面に見えるのにスクリーンリーダーが読まないテキスト」を参照してください。
  • role="widget" のような抽象ロールを使う。 WAI-ARIAが禁じており、HTML-AAMの3.5.1節も、ブラウザーは抽象ロールや無効なロールを無視しなければならない(MUST)としています。使えるロールはHTMLとARIAのリファレンスを参照してください。
  • title や placeholder を名前の代わりにする。 HTML-AAMがこれらを使うのは、ほかに名前がないときだけです。placeholderは入力を始めると画面から消えます。「ラベルがない・表示と食い違うフォームの入力欄」を参照してください。

09

規格の定め

  • WCAG 2.2 達成基準4.1.2「名前 (name) ・役割 (role) 及び値 (value)」(レベルA、要件): フォーム要素、リンク、スクリプトが生成するコンポーネントを含むすべてのユーザーインターフェイスのコンポーネントについて、名前と役割をプログラムで解釈できること、利用者が設定できる状態、プロパティ、値をプログラムで設定できること、それらの変化の通知が支援技術を含むユーザーエージェントに提供されることを求めています。EN 301 549 V3.2.1では9.4.1.2として同じ要件があります。WCAG 2.0と同じ内容のJIS X 8341-3:2016では4.1.2です。Section 508(E205.4)はWCAG 2.0のレベルAとAAを求めているので、これも含まれます。
  • WAI-ARIA 1.2(W3C勧告、2023年6月6日)、ARIAを使うコンテンツへの要件: 「作成者は抽象ロールをコンテンツに使ってはならない(MUST NOT)」(5.3.1節)。aria-hidden については、見えている内容をスクリーンリーダーから隠す場合、同じか同等の意味と機能を支援技術に公開しなければならない(MUST)としています。1.3節と6.1節は仕組みの説明で、要件ではありません。
  • AccName 1.1(W3C勧告、2018年12月18日)、ブラウザーへの要件: その手順でアクセシブル名を計算しなければならない(MUST)としています(4.1節)。AccName 1.2は草案です。新しい版が出たかどうかは、W3Cの公開履歴で確かめられます。
  • HTML-AAM 1.0(草案、2026年10月26日)とCore-AAM 1.2(勧告候補草案、2026年10月30日): ブラウザーが何をどう対応させるかを定めるもので、作成者が書く内容を定めるものではありません。Core-AAMの最新の勧告は1.1です。
  • Using ARIA(作業中止の草案、2026年2月24日): 助言だけで、今後は更新されません。

10

制限

この記事が扱うのは、ツリーに何が届くかまでです。次のことは扱いません。

コントロールの名前や説明が利用者にとって適切かどうかは、実際のページを見てテスト担当者が判断します。

11

用語

アクセシビリティツリー
ブラウザーがDOMから支援技術のために作る、アクセシブルなオブジェクトの木構造。各オブジェクトがロール、名前、状態、関係を持つ。
アクセシビリティAPI
アプリケーションの各部分を支援技術が読み取り、操作するためにOSが用意するインターフェイス。WindowsのUI Automationなど。
アクセシブル名
アクセシビリティツリーでオブジェクトを特定する短い文字列。ボタンのラベルなど。
アクセシブルな説明
名前とは別に、オブジェクトについて補足する文字列。入力欄の下のヒントなど。
暗黙のロール
role属性がないときにHTML要素が持つロール。HTML-AAMが対応を定めている。button要素はbutton、nav要素はnavigation。
抽象ロール
WAI-ARIAがロールの体系を作るためだけに使うロール。widgetやinputなど。作成者はコンテンツに使ってはならない。

12

出典とガイド

関連するガイド

この記事は実務の進め方を、再現した例で説明するものです。スクリーンリーダーでのテスト結果ではなく、特定の顧客についての指摘でもありません。