1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

あなたが書いたHTMLは、どうやってスクリーンリーダーまで届くのか

1
Posted at

はじめに: aria-labelを書いたあと、何が起こっている?

次のコードから考えてみます。

<button aria-label="保存">
  💾
</button>

一般的なアクセシビリティ解説では、「aria-labelに『保存』と設定したので、支援技術にボタンの名前を伝えられる」と説明されることがあります。

では、なぜHTML属性であるaria-labelを、スクリーンリーダーが知ることができるのでしょうか。スクリーンリーダーがHTMLソースをそのまま読んでいるわけではありません。

HTML
  ↓
???
  ↓
スクリーンリーダー

この「???」にあるレイヤーを追うのが、この記事の目的です。WebアクセシビリティをARIA属性の書き方だけではなく、UIの意味がユーザーまで届く情報伝達経路として見ていきます。

HTMLからDOMへ

ブラウザーはHTMLを解析し、要素・属性・テキストをDOM(Document Object Model)として扱います(WHATWG HTML Standard)。パース処理の詳細はここでは扱いません。ReactなどのUIフレームワークを使っていても、ブラウザーが扱う段階ではDOMが土台になります。

ただし、DOMそのものが支援技術へ渡る最終的なUI表現ではありません。DOMには画面の構造やスクリプトが扱う情報が含まれますが、支援技術が知りたいのは、たとえば「これは何のUIか」「名前は何か」「操作できるか」「現在どんな状態か」です。

この意味を公開するために、ブラウザーはDOMの情報をAccessibility Treeへつなぎます。

DOMからAccessibility Treeへ

ブラウザーはDOMやHTMLの意味、ARIA属性などをもとに、Accessibility Tree(アクセシビリティツリー)を構成します。これは支援技術へ公開する意味を理解するためのモデルです。WAI-ARIAはARIAのロール・状態・プロパティの意味を定義し、Accessible Name and Description Computationは名前や説明の計算方法を定めています。仕様がブラウザー内部に同一のツリー実装を要求している、ということではありません。Chrome DevToolsで見えるツリーは、Chromeが計算・公開する情報を観察するためのものです。

Accessibility Tree上の情報は、次のように考えられます。

情報 何を表すか 例
Role(役割) どのようなUIか button、link
Name(名前) そのUIを何と呼ぶか 保存、検索
Description(説明) 名前を補う情報 入力形式や追加の案内
State / Properties(状態・プロパティ) 現在の状態や関係 無効、展開中、チェック済み

例のHTMLを、概念的に表すと次のようになります。

role: button
name: 保存

<button>にはHTMLにもともと「ボタン」という意味があり、aria-labelが「保存」というアクセシブルネームを与えます。この例では、ボタン名の計算にaria-labelが使われるため、絵文字の読み方ではなく操作の目的を名前として公開できます。名前の計算にはaria-labelledbyなど別の命名方法との優先関係もありますが、ここではほかの命名方法がないものとします。

理解のために単純化すると、次の対比になります。

DOM
→ UIがどのように実装されているか

Accessibility Tree
→ UIがどのような意味として公開されているか

ただし、これは役割の違いをつかむための単純化です。DOMとAccessibility Treeが一対一で変換されるわけではありません。たとえば、DOM上にあってもアクセシビリティ上不要なノードは公開されないことがあります。一方、CSSで生成されたコンテンツなど、DOMに直接対応する要素がない情報がツリーに現れることもあります。Chromeの実装資料も、DOMとアクセシビリティツリーが一対一ではない例を挙げています。

そのため、アクセシビリティ対応の目的はARIA属性を書くこと自体ではありません。意図した名前・役割・状態などの意味が、支援技術へ適切に公開されるよう設計することです。

Chrome DevToolsで3つの例を比べる

ここで、説明だけで終わらないように、3つの要素を同じページに置いてChrome DevToolsで比べてみます。

<main>
  <button id="native-button">保存</button>

  <div id="plain-div">保存</div>

  <button id="named-button" aria-label="ファイルを保存">
    💾
  </button>
</main>

Chrome DevToolsの現行ドキュメントに沿って確認するには、Elementsパネルで対象要素を選び、Accessibilityタブを開きます。タブが見つからない場合はMore Tabsにあります。各要素のARIA属性やComputed Propertiesを見た後、同じタブでShow accessibility treeを有効にすると、ページ全体のツリーを確認できます。

同じ3要素をChromeで観察すると、次のような違いが見えます。

パターン DOM上の要素 Chromeが公開するrole / name Tabキーでフォーカス
1 buttonとテキスト「保存」 button / 保存 できる
2 divとテキスト「保存」 generic / 要素自体の名前なし。子テキストは別に見える 通常はできない
3 buttonとaria-label、絵文字 button / ファイルを保存 できる

パターン1では、<button>のネイティブな意味からroleと名前が得られます。ARIAを追加しなくても、ボタンとしてTabキーでフォーカスできます。

パターン2は、見た目に文字が表示されていても、ボタンの役割やキーボード操作はありません。今回Chromeで確認したツリーでは、divはgenericとして現れ、テキストは子のノードとして確認できました。つまり、文字が読めることと、操作要素として意味が伝わることは別です。

パターン3では、ネイティブボタンのroleとキーボード操作はそのままに、アクセシブルネームがaria-labelの「ファイルを保存」になります。子の絵文字がボタンの名前になるのではなく、指定した名前が公開されます。

表のTabキーの列は、Accessibility Treeのroleやnameだけから判断するものではありません。実際にページでTabキーを押してフォーカス位置を確かめます。HTML要素の既定のフォーカス動作については、MDNのtabindex解説も参照してください。divでもtabindexを追加すればフォーカス可能にはできますが、それだけでボタンのroleやキーボード操作が備わるわけではありません。

Accessibility Treeはゴールではない

ここまで、次の経路を追ってきました。

HTML
  ↓
DOM
  ↓
Accessibility Tree

しかし、支援技術が利用できる情報になるまでには、その先のレイヤーがあります。

HTML
        ↓
DOM
        ↓
Accessibility Tree
        ↓
Platform Accessibility API
        ↓
支援技術
        ↓
ユーザー

WindowsやmacOSなどでは、それぞれ異なるAccessibility APIが使われます。たとえばWindowsのUI Automation、macOSのAccessibility API、LinuxのATK/AT-SPIは別々のインターフェースです。W3CのHTML-AAMとCore-AAMは、HTMLやARIAが表す意味を、各プラットフォームのAPIにどう対応づけるかを扱っています。

たとえばWindowsでは、UI Automation(UIA)がUI要素をツリーとして公開し、要素のコントロール種別やNameなどの情報をクライアントから取得できるようにします。Microsoft Edgeの資料は、EdgeがARIAのロール・状態・プロパティを認識し、支援技術がUI Automation APIを使ってそれらを取得できるよう公開すると説明しています。

したがって、次のような単純な構造ではありません。

ARIAを書く → スクリーンリーダーがARIAを直接読む

また、「スクリーンリーダーはAccessibility Treeを直接読む」とも限りません。Accessibility Treeはブラウザー内部の意味表現として考えると分かりやすい一方、支援技術との接点は、環境ごとのPlatform Accessibility APIです。内部のデータ構造や連携方法は、ブラウザー・OSの実装によって異なります。

DevToolsで正しければアクセシブルなのか?

答えは「それだけでは十分ではない」です。Accessibility Treeの確認で分かるのは、情報伝達経路のうち、ブラウザーがUIの意味をどう公開しているかです。利用者が実際に操作できるか、目的を理解できるかは、それだけでは確かめきれません。

DOMを見る
  ↓
実装を確認する

Accessibility Treeを見る
  ↓
ブラウザーがUIの意味をどう公開しているか確認する

キーボードやスクリーンリーダーで操作する
  ↓
実際の操作体験を確認する

スクリーンリーダーはAPIから得た名前・役割・状態を使いますが、読み上げる順序や言い回しは常に同一ではありません。W3CのAccessible Name and Description Computationも、役割と名前の提示方法などはプラットフォームAPIや支援技術によって決まると説明しています。実際の読み上げや操作を確認するには、対象とするブラウザーとスクリーンリーダーの組み合わせで試す必要があります。

つまり、「自動テストを通過したからアクセシブル」「Accessibility Treeが正しいからアクセシブル」とは言えません。DOM、ブラウザーが公開する意味、キーボード操作、支援技術を使った体験を、それぞれの段階で確かめることが大切です。

ReactやUIフレームワークを使うと、この経路はどうなる?

Reactでは、コンポーネントの中にaria-labelを書きます。しかしReactがスクリーンリーダーへラベルを直接送るわけではありません。Reactのドキュメントでも、aria-*属性は組み込みのDOMコンポーネントで使われ、属性名はHTMLと同じと説明されています。レンダリング結果のDOMをブラウザーが解釈し、その先のAccessibility TreeやPlatform Accessibility APIへつなぎます。

React Component
        ↓
UI Component Library(Fluent UIなど)
        ↓
DOM
        ↓
Accessibility Tree
        ↓
Platform Accessibility API
        ↓
JAWS / NVDA / Narrator など
        ↓
ユーザー

UIフレームワークやコンポーネントライブラリは、適切なHTMLやARIAを出力する助けになります。ただし、それだけでユーザーまで意味が正しく届く保証にはなりません。レンダリング後のDOMを確認し、ブラウザーが計算した情報と、実際の支援技術での操作を確かめるという流れは変わりません。

おわりに: アクセシビリティを「情報の経路」として考える

aria-labelは、スクリーンリーダーへの音声命令ではありません。HTML上の情報がDOMに入り、ブラウザーが役割や名前などの意味を計算し、Accessibility TreeやPlatform Accessibility APIを通じて支援技術へ届きます。支援技術はその情報を、環境やユーザーの操作に応じた形で提示します。

HTML / UI Framework
        ↓
DOM
        ↓
Accessibility Tree
        ↓
Accessibility API
        ↓
支援技術
        ↓
ユーザー

ARIA属性のテクニックだけを見るのではなく、途中の各レイヤーで意味が保たれているかを確かめる。アクセシビリティを情報伝達の経路として捉えることで、「なぜARIAが効くのか」だけでなく、「どこで意図が失われるのか」も考えやすくなります。

次の記事では、今回の経路にShadow DOMが加わると何が起きるのかを考えます。Shadow DOMの向こう側は支援技術からどう見えるのでしょうか?

私たちが作っているのはDOMそのものではありません。その先にいるユーザーへ届くUIを作っています。

参考資料

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?