アクセシビリティオブジェクトモデル

著者:

Table of Contents

はじめに

このJavaScript APIを作る努力の目的は、開発者にHTMLページのアクセシビリティツリーの変更(ついには探索まで)を許可するためである。

モチベーションとなるユースケース

既存のAPIの背景は付録で見つけることができる。

ウェブ上でできることの境界を押し広げているウェブアプリケーションは、APIが不十分なためそれらをアクセシブルにするため苦闘している。特に、ブラウザとやりとりするネイティブAPIと比較して表現力に劣っている。

  1. ページの著者が上書きできるウェブコンポーネントのデフォルトアクセシビリティプロパティの設定
    • 現在、ウェブコンポーネントのデフォルトセマンティクスを定義するにはARIAを使用しなければならない。 これにより、真に詳細な実装であるARIA属性がDOMに「リーク」してしまう。
    • このことは必要では なく ウェブコンポーネントに限られる かも 知れない。
  2. IDREFs を必要としない関係属性の設定
    • 現在、いくつかのARIAの関係を示すには、著者が一意のIDを関係の対象となりうる要素に指定しなければならない
    • aria-activedescendantのような場合、 それはUIに応じて、数百ないしは数千もの要素のうち、一つを参照するかもしれない。 この要求は、多くの余分なDOMの属性が必要となり、これらのAPIを複雑にする。
  3. 支援技術からのイベントをリスニングする
    • 現在、組み込み要素 だけ がイベントに反応することができ、 通常、「simulated click」「increment」 のようなユーザーアクションによって引き起こされる。
  4. アクセシビリティツリーにDOMでないノード(仮想ノード)を追加する
    • 例えば、<canvas> 要素で構築された複雑なUIや、<video> 要素を用いたリモートデスクトップのストリーミングなどを表現するなど
    • そのためには、少なくとも要素と同じようなアクセシビリティプロパティや、他の仮想ノードとの親/子/その他の関係性、位置や次元を表す必要がある。
  5. 計算済のアクセシビリティツリーの確認
    • 開発者は現在、ARIAやその他のアクセシビリティプロパティがどのように適用されているかを調べたりテストする方法を持っていない。

アクセシビリティオブジェクトモデル

アクセシビリティオブジェクトモデル (AOM)は、上記のユースケースに取り組むためのHTMLや関連する標準に対する一連の変更である。

(注: 以前のバージョンのAOMに慣れ親しんでいれば、AccessibleNodeに何が起こったのか?と疑問を持つかもしれない。)

ARIA属性を反映する

ARIA 属性をHTML要素に反映する

これは今ARIA 1.2の仕様の一部となった。

el.role = "button";
el.ariaPressed = "true";  // aria-pressed は3つのステートを持つ属性
el.ariaDisabled = true;   // aria-disabled は true/false を持つ属性

要素の参照を反映する

ARIAプロパティの直接的反映。aria-labelledby のような関係属性の文字列に反映させる。

el.ariaDescribedBy = "id1";

結果は

<div aria-describedby="id1">

要素を参照する非反映のプロパティでAPIを拡張することを提案する。

el.ariaDescribedByElements = [labelElement1, labelElement2];
el.ariaActiveDescendantElement = ownedElement1;

これにより、関係に属するそれぞれの要素にグローバルに固有なID属性を割り当てることなく要素間のセマンティクスの関係性を示すことができる。

さらにこれは、ShadowRootを使用した著者がShadow DOMの境界を超えて関係性を明示することを可能にする

このAPIはWHATWG HTML仕様の変更として提案されている。

ユースケース 2: IDREFsを使用することなく関係プロパティを設定する

現在、Shadow DOMの境界を超えて関係を表そうとする著者は次のように aria-activedescendant の使用を試すだろう。

<custom-combobox>
  #shadow-root (open)
  |  <!-- これはうまくいかない! -->
  |  <input aria-activedescendant="opt1"></input>
  |  <slot></slot>
  <custom-optionlist>
    <x-option id="opt1">Option 1</x-option>
    <x-option id="opt2">Option 2</x-option>
    <x-option id='opt3'>Option 3</x-option>
 </custom-optionlist>
</custom-combobox>

これは失敗で、なぜならIDREFsはshadowRoot、またはそれらが現れる文書の文脈の範囲に限られる。

著者は代わりにこの関係性をプログラムで示すことができる。

const input = comboBox.shadowRoot.querySelector("input");
const optionList = comboBox.querySelector("custom-optionlist");
input.activeDescendantElement = optionList.firstChild;

このことにより、関係が自然に表現されるようになる。

このAPIはWHATWG HTMLリポジトリのissue #3513で議論されている。

カスタム要素のAPI

カスタム要素の著者が customElements.define() オプションを用いて静的なデフォルトセマンティクス、または設定されたコールバックを用いて動的に要素ごとのセマンティクスを提供できることを提案する。

ユースケース1: 非反映のデフォルトアクセシビリティプロパティをウェブコンポーネントに設定する

今、ウェブコンポーネントを制作するライブラリの著者はネイティブ要素にとっては暗黙であるセマンティクスを表すためにARIA属性を「生やす」ことを強いられている。

<!-- ページの著者はカスタム要素をネイティブ要素を使用するように使用する -->
<custom-tablist>
  <custom-tab selected>Tab 1</custom-tab>
  <custom-tab>Tab 2</custom-tab>
  <custom-tab>Tab 3</custom-tab>
</custom-tablist>

<!-- カスタム要素がセマンティクスを表すために余分な属性を「生やす」ことを強制される -->
<custom-tablist role="tablist">
  <custom-tab selected role="tab" aria-selected="true" aria-controls="tabpanel-1">Tab 1</custom-tab>
  <custom-tab role="tab" aria-controls="tabpanel-2">Tab 2</custom-tab>
  <custom-tab role="tab" aria-controle="tabpanel-3">Tab 3</custom-tab>
</custom-tablist>
customElements.define() を利用したデフォルトセマンティクス

著者は CustomElementRegistry.define() メソッドに渡された ElementDefinitionOptions オブジェクトを利用して、不変のデフォルトセマンティクスをカスタム要素に提供することもできる。

ElementDefinitionOptions オブジェクトに設定されたプロパティは、カスタム要素をアクセシブルなオブジェクトにマッピングする際に、デフォルトの値として利用される。

注: これは「不変なクラス変数」を作るのに類似している。これらのセマンティクスプロパティはカスタム要素の定義に関連付けられていて、カスタム要素のインスタンスには関連していない。

定義されたセマンティクスは すべての カスタム要素のインスタンスに適用される。

例えば、カスタムタブコントロールを作成する著者は、タブ、タブリスト、タブパネルの3つのカスタム要素を個々に定義することができる。

class TabListElement extends HTMLElement { ... }
customElements.define("custom-tablist", TabListElement,
                      { role: "tablist", ariaOrientation: "horizontal" });

class TabElement extends HTMLElement { ... }
customElements.define("custom-tab", TabElement,
                      { role: "tab" });

class TabPanelElement extends HTMLElement { ... }
customElements.define("custom-tabpanel", TabPanelElement,
                      { role: "tabpanel" });

<custom-tab> がアクセシビリティツリーにマッピングされるとき、タブのロールがデフォルトでマッピングされる。

これは button 要素がデフォルトでボタンのロールを持ってアクセシビリティオブジェクトにマッピングされるのに似ている。

ElementInternals オブジェクトを利用した動的なインスタンス単位のセマンティクス

これはW3C Web Componentsプロジェクトの一部として議論されている.

カスタム要素の著者は ElementInternals オブジェクトを、ユーザーインタラクションに応じてカスタム要素のインスタンスのセマンティクスの状態を変更するのに利用できる。

ElementInternals オブジェクトにセットされたプロパティはアクセシビリティオブジェクトに要素をマッピングされる際に利用される。

注: これは「インスタンス変数」を設定するのに類似している。セマンティクスプロパティのコピーはカスタム要素のインスタンス毎に作られる。それぞれに定義されたセマンティクスは関連するカスタム要素のインスタンスオブジェクトにのみ関連付けられる。

class CustomTab extends HTMLElement {
  #internals = null;
  #tablist = null;
  #tabpanel = null;

  constructor() {
    super();
    this.#internals = customElements.createInternals(this);
    this.#internals.role = "tab";
  }

  // カスタム「active」属性を監視する
  static get observedAttributes() { return ["active"]; }

  connectedCallback() {
    this.#tablist = this.parentElement;
  }

  setTabPanel(tabpanel) {
    if (tabpanel.localName !== "custom-tabpanel" || tabPanel.id === "")
      return;  // 静かに失敗する

    this.#tabpanel = tabpanel;
    tabpanel.setTab(this);
    this.#internals.ariaControls = tabPanel;    // 反映されない
  }

  // 属性に反映するカスタムプロパティの setters/getters

  attributeChangedCallback(name, oldValue, newValue) {
    switch(name) {
      case "active":
        let active = (newValue != null);
        this.#tabpanel.shown = active;

        // カスタム「active」属性が変更された時、
        // アクセシブルな「selected」ステートを同期し続ける
        this.#internals.ariaSelected = (newValue !== null);

        if (selected)
          this.#tablist.setSelectedTab(this);  // 他のタブが 「active」で無いことを保証
        break;
    }
  }
}

customElements.define("custom-tab", CustomTab, { role: "tab", needsElementInternals: true });

これらの要素を使用する著者は通常通りARIAを用いてデフォルトセマンティクスを上書きすることができる。

例えば、著者は <custom-tablist> 要素の見た目を縦並びに変更できる。彼らはそれを示すために aria-orientation 属性を追加することで、カスタム要素に定義されているデフォルトセマンティクスを上書きすることができる。

<custom-tablist aria-orientation="vertical" class="vertical-tablist">
  <custom-tab selected>Tab 1</custom-tab>
  <custom-tab>Tab 2</custom-tab>
  <custom-tab>Tab 3</custom-tab>
</div>

著者が提供するロールがデフォルトのロールを上書きするので、それぞれの場合においてマッピングされるロールは著者が提供するロールに基づく。

仮に著者によって提供されたセマンティクスがカスタム要素のセマンティクスと競合する場合でも著者が提供するセマンティクスが優先される。

支援技術からのユーザーアクションイベント

支援技術ユーザーのプライバシーを保護するために、通常、支援技術からのイベントは合成されたDOMイベントを発生させる。

支援技術のイベント ターゲット DOMイベント
click すべての要素 click
focus すべての要素 focus
select cell または option ロールがマッピングされた要素 click
scrollIntoView (n/a) イベントなし
dismiss すべての要素 Escape キーのキーが押されたシーケンス
contextMenu すべての要素 contextmenu
scrollByPage すべての要素 スクロール方向に応じた PageUp または PageDown キーが押されたシーケンス
increment progressbarscrollbarslider または spinbutton ロールがマッピングされた要素 Up キーのキーが押されたシーケンス
decrement progressbarscrollbarslider または spinbutton ロールがマッピングされた要素 Down キーが押されたシーケンス
setValue comboboxscrollbarslider または textbox キーが押されたシーケンス 未定

新しい入力イベントタイプ

いくつかのInput Event タイプを追加する:

これらのイベントは上記の表に記載された合成キーボードイベントと共に支援技術のイベントから引き起こされ、 また上記の関連する支援技術のイベントに対応した有効なターゲットの文脈の中で発生したときに合成される。

例えば、もしある文脈で支援技術を使用していないユーザーが Escape キーを押した場合、キーが押されたシーケンスで dismiss タイプを伴った input イベントが発火する。

もし同じユーザーが <input type="range"> または (計算された slider ロールを含む)slider ロールを持った要素上にフォーカスがある Up キーを押した場合、キーが押されたシーケンスで increment タイプを伴った input イベントがフォーカスされた要素で発火される。

ユースケース3: 支援技術からのイベントをリッスンする

例えば:

現在、ブラウザーはネイティブHTML要素の組み込みサポートを実装することによって、アクセシビリティアクションを一部実装している。(例えばネイティブHTMLの <input type="range"> はすでに増加・減少アクションをサポートし、テキストボックスは値を設定したりテキストを挿入するアクションをサポートしている。)

しかしウェブページの著者がカスタムエレメント上のアクセシビリティアクションをリッスンする方法が無い。 例えば、slider ロールを持ったカスタムスライダー 上ではiOSのVoiceOverでは増加・現象のためにスワイプアクションを促す提案がされるが、いかなるウェブAPIもそのセマンティックイベントを扱うことができない。

開発者はセマンティックイベントを補足するようなキーボードイベントまたは入力イベントをリッスンすることができるようになるだろう。

例えば、著者はカスタムスライダーを実装するために ARIA Authoring Practices guideで推奨されている UpDown キーイベントを扱うことができ、同じように支援技術のイベントも扱うことができる。

customSlider.addEventListener('keydown', (event) => {
  switch (event.code) {
  case "ArrowUp":
    customSlider.value += 1;
    return;
  case "ArrowDown":
    customSlider.value -= 1;
    return;
});

仮想アクセシビリティノード

仮想アクセシビリティノード は著者に、支援技術に特定のDOM要素に直接関係のない 仮想 のアクセシビリティノードに触れさせられることができる。

このメカニズムは、著者がカスタム描画APIのアクセシビリティをよりきめ細かくコントロールするためにネイティブアクセシビリティAPIによく存在する。

// AccessibuleNode は仮想のアクセシビリティノードを表している。
interface AccessibleNode {
    attribute DOMString? role;
    attribute DOMString? name;

    attribute DOMString? autocomplete;
    // ... その他すべてのARIAと同等の属性

    // 仮想ノードのためだけの重要なARIAと同等でない属性
    attribute DOMString? offsetLeft;
    attribute DOMString? offsetTop;
    attribute DOMString? offsetWidth;
    attribute DOMString? offsetHeight;
    attribute AccessibleNode? offsetParent;

    // アクセシブルフォーカスだけの影響
    boolean focusable;

    // ツリーをたどる
    readonly attribute AccessibleNode? parent;
    readonly attribute ComputedAccessibleNode? firstChild;
    readonly attribute ComputedAccessibleNode? lastChild;
    readonly attribute ComputedAccessibleNode? previousSibling;
    readonly attribute ComputedAccessibleNode? nextSibling;

    // アクション
    void focus();

    // ツリーの変更
    AccessibleNode insertBefore(AccessibleNode node, Node? child);
    AccessibleNode appendChild(AccessibleNode node);
    AccessibleNode replaceChild(AccessibleNode node, AccessibleNode child);
    AccessibleNode removeChild(AccessibleNode child);
};

partial interface Element {
  AccessibleNode attachAccessibleRoot();
}

ユースケース4; DOMでない仮想のノードをアクセシビリティツリーに追加する

例えば、<canvas> 要素から構築された複雑なUIを表すには:

// canvas ベースのスプレッドシートのセマンティクスを実現する
canvas.attachAccessibleRoot();
let table = canvas.accessibleRoot.appendChild(new AccessibleNode());
table.role = 'table';
table.colCount = 10;
table.rowcount = 100;
let headerRow = table.appendChild(new AccessibleNode());
headerRow.role = 'row';
headerRow.rowindex = 0;
// などなど

仮想ノードは通常位置と寸法を明示的に設定する必要がある。

cell.offsetLeft = "30px";
cell.offsetTop = "20px";
cell.offsetWidth = "400px";
cell.offsetHeight = "300px";
cell.offsetParent = table;

もし offsetParent を設定しない場合、アクセシブルノードの親を基準として解釈される。

ノードをフォーカスできるようにする場合、 focusable 属性を設定することができる。これは tabIndex=-1 をDOM要素に設定するのに似ている。

virtualNode.focusable = true;

仮想アクセシブルノードはデフォルトではフォーカスできない。

最後に、アクセシビリティノードにフォーカスするには、 focus() メソッドを実行する。

virtualNode.focus();

仮想アクセシブルノードがフォーカスされたとき、DOMのフォーカスは変わらない。アクセシビリティノードのフォーカスは、支援技術や他のアクセシビリティAPIクライアントに伝わるが、DOMイベントは発火せず document.activeElementも変わらない。

DOM要素のフォーカスが変わった時、アクセシブルフォーカスも追従し、DOM要素に関連付けられたアクセシブルノードがフォーカスされる。

ComputedAccessibleNode によるアクセシビリティツリーの完全な確認

partial interface Window {
  [NewObject] ComputedAccessibleNode getComputedAccessibleNode(Element el);
}
interface ComputedAccessibleNode {
    // アクセシビリティノードと同じだが、読み取り専用
    readonly attribute DOMString? role;
    readonly attribute DOMString? name;

    readonly attribute DOMString? autocomplete;
    // ... その他すべてのARIAと同等の属性

    // ARIAと同等でない属性
    readonly attribute DOMString? offsetLeft;
    readonly attribute DOMString? offsetTop;
    readonly attribute DOMString? offsetWidth;
    readonly attribute DOMString? offsetHeight;
    readonly attribute AccessibleNode? offsetParent;
    readonly boolean focusable;

    readonly attribute AccessibleNode? parent;
    readonly attribute ComputedAccessibleNode? firstChild;
    readonly attribute ComputedAccessibleNode? lastChild;
    readonly attribute ComputedAccessibleNode? previousSibling;
    readonly attribute ComputedAccessibleNode? nextSibling;
};

ユースケース5: 計算されたツリーを確認する

計算されたアクセシビリティツリー APIは著者に、完全な計算されたアクセシビリティツリーにアクセスすることを許可する。それぞれのDOM要素に関連付けられたアクセシビリティノードのすべての計算されたプロパティに加え、仮想ノードを含む計算された木構造を走査可能にする。

このことは次のことを可能にする:

なぜ最終的に計算されたプロパティにアクセスするのか

一貫性 現在、アクセシビリティツリーはブラウザ間で標準化されていない。それぞれのアクセシビリティツリーの計算は実装がわずかに異なる。

このAPIが役に立つには、ブラウザ間で一貫して動作することが必要で、開発者はそれぞれに特別なコードを書く必要がない。

我々はツリーがどのように計算され表現されるかについて合意ができるよう十分な時間をかけていきたいと考えている。

パフォーマンス 多くのアクセシビリティプロパティを計算するにはレイアウトが必要となる。ウェブ制作者に単純なプロパティアクセスと同期してアクセシビリティプロパティの計算された値を調べることを許可すると、パフォーマンスのボトルネックに混乱をもたらしてしまう。

このことから accessibleNode インターフェースの一部を意味しない非同期的なメカニズムを作成したいと考えている。

ユーザー体験 前の3つと比較して計算されたアクセシビリティツリーにアクセスすることはユーザーに与える影響が最小限となる。優先順位の構成要素の考え方の元、このことに最後に取り組むことは理にかなっている。

このAPIの対象者

このAPIは主に、ウェブアプリの多くを動かしているJavaScriptフレームワークやウィジェットライブラリーを制作、メンテナンスしている比較的少数の開発者に興味を持たれるだろう。

それらのフレームワークやライブラリーにとってアクセシビリティは、可能な限り幅広く多様な文脈で使用されるようになるため、重要な目標の一つである。

低レベルのAPIによって彼らは制約やバグを回避し、彼らの制作したコンポーネントを使用する開発者のためにクリーンな高レベルのインターフェースを提供できるようになる。

このAPIはウェブプラットフォームの境界を押し広げるような巨大なフラッグシップウェブアプリの開発者をも対象としている。

これらのアプリの開発チームでは、Canvasのような低レベルAPIを利用してでもパフォーマンスを向上させたがっていることがしばしばある。

そのような開発チームだと、アクセシビリティを優先するだけのリソースもあるが、既存のAPIでは非常に面倒である。

AccessibleNodeに何が起こったのか?

当初の意図としては、これまでのユースケースを読み書き可能なAPIにまとめるものだった。それはそれぞれのDOMの Element に、アクセシビリティプロパティを読み込んだり書き込んだりできる AccessibleNode が関連付けられているという点でDOMに似ていた。

これはドキュメントオブジェクトモデルと似たようなアクセシビリティオブジェクトモデルと命名された。

しかし、議論が進むにつれこのモデルにはいくつかの問題があることがわかってきた。

これらの問題により、APIをもともと対処するつもりだったユースケースに基づいて再評価、そして簡素化することとなった。

次のステップ

アクセシビリティオブジェクトモデルの開発は、現在の主要なブラウザベンダーを代表した編集者のチームがリードしている。

GitHub上で問題を報告することができる。

https://github.com/WICG/aom/issues

インキュベーション

Web Platform Incubator Community Group (WICG)の一部としてこの仕様の開発は継続するつもりだが、時が経てば自身のコミュニティグループに開発が移るかもしれない。

このグループの活動は、ARIAなどのWeb Accessibility Initiativeの現在の活動からは全体的にほとんど独立している。

ARIAがWeb上のアクセシビリティプロパティのための構造的なマークアップとセマンティクスを定義している際には、しばしば支援技術のベンダーやネイティブプラットフォームのAPIと調整をしなければならないが、AOMは単に開発者のためにより低レベルの制御ができる並列のJavaScriptのAPIを提供し、ウェブプラットフォームのギャップを埋めるにとどまり、新しいセマンティクスを導入することは無い。

謝辞

価値のあるフィードバックや助言、ツールを提供してくれた

に多大な感謝を。

マイクロソフトの Bogdan Brinza と Cynthia Shelley は現在は積極的に参加していないが、この仕様の最初の草案に貢献した。

付録

背景: 支援技術とアクセシビリティツリー

この仕様の中で支援技術は、アプリケーションの既存のUIを補強したり置き換えたりする第三者のアプリケーションのことを指す。よく知られた例の一つとしてスクリーンリーダーがある。スクリーンリーダーは視覚的でポインターベースのUIを、聴覚出力(音声、およびトーン)と、キーワード、ジェスチャーの両方、またはいずれかによる入力メカニズムに置き換える。

多くの支援技術は、アクセシビリティAPIを通じてウェブページとやりとりする。たとえば、Windows上のUIAutomationや、OS XのNSAccessibilityなどがある。これらのAPIを利用するとアプリケーションのインターフェースを示すオブジェクトのツリーを公開することができる。アプリケーションウィンドウのことを示すルートノードから、個々のインタラクティブな要素まで様々なレベルのノードがグループ化されている。これは アクセシビリティツリー と呼ばれている。

支援技術がアクセシビリティツリーを使って代替インターフェースを作り、ユーザーの命令で発火したインタラクションイベントが支援技術にルーティングされ、支援技術のユーザーはほぼこのAPIを通じてアプリケーションとやりとりをする。

アプリケーションUIからアクセシビリティツリー、支援技術、ユーザーまでの流れ

代替インターフェースの 出力 (例えば、音声やトーン、点字ディスプレイの更新、スクリーンルーペのフォーカスの移動)、また 入力 (例えば、キーボードショートカット、ジェスチャー、点字ルーティングキー、スイッチ機器、音声入力など)は完全に支援技術の責務で、アプリケーションの役割ではない。

例えば、OS Xのネイティブアプリケーションを使用するVoiceOverユーザーは、「control、option、スペースバー」キーの組み合わせ押す。それはスクリーンリーダーが現在いるUI要素をクリックするということを示す。

UIの要素からアクセシビリティノード、支援技術、ユーザー、ユーザーのキー操作、アクセシビリティAPIのアクションをUI要素に戻す往復

これらのキー押下はアプリケーションに渡されることはないが、スクリーンリーダーが受け取り、accessibilityPerformPress()関数を該当のUI要素を示すアクセシビリティノード上で実行する。アプリケーションはプレスアクションを処理し、通常はクリックイベントを処理するコードにルーティングされる。

アクセシビリティAPIはテストや自動化でもよく利用される。それらは堅牢で包括的な方法でアプリケーションの状態を調査、またプロセスの外からUIを操作する方法を提供する。通常、アクセシビリティAPIの主な動機は障害を持つユーザーのための支援技術だが、これらのAPIが一般的で多くの用途があることを理解することは重要である。

アクセシビリティノードプロパティ

アクセシビリティツリーの各ノードは アクセシビリティノード と呼ばれる。

アクセシビリティノードは常に一つのセマンティックな目的を示す ロール を持つ。 これは単に他のノードを包含することを示すグループ化するロールであってもよいし、または "button" のようなインタラクティブなロールであってもよい。

アクセシビリティツリーの中のアクセシビリティノード。ロール、名前、状態とプロパティを示している。

ユーザーは支援技術を介して、様々なレベルでアクセシビリティツリーを探索することができる。かれらは、ランドマーク要素のようなユーザーのページのセクションへの移動を助けるグループ化されたノードとやり取りすることができたり、ボタンのようなインタラクティブなノードとやり取りすることができる。

それらの双方の場合において、文脈の中でのノードの役割を示すため、ノードは通常 ラベル (しばしば 名前 と呼ばれる)を必要とする。例えば、ボタンは「OK」や「メニュー」というラベルを持つ。

アクセシビリティノードはまた現在の (範囲であれば "10" だったり、テキスト入力であれば "ジェーン" であったり)のような他のプロパティを持ったり、(チェックボックスの "checked" または "focused"など)の状態の情報を持つことができる。

インタラクティブなアクセシビリティノードは、それらに対して実行される特定の アクション も持つことができる。例えば、ボタンは "press" アクションを公開するし、スライダーは "increment""decrement" アクションを公開する。

これらのプロパティとアクションはノードの セマンティクス と呼ばれる。各アクセシビリティAPIにおいて少しずつ違いはるが、概念的にはほとんど似ている。

背景: DOMツリー、アクセシビリティツリー、そしてプラットフォームのアクセシビリティAPI

ウェブはアクセシブルなアプリケーションを制作するのに多くのサポートを提供しているが、それらは 宣言的 なAPIを通じてのみである。

DOMツリーは並行して主にページの視覚的な表現とアクセシビリティツリーに変換される。アクセシビリティツリーは、一つまたは複数の プラットフォーム固有の アクセシビリティAPIを介してアクセスされる。

HTMLがDOMツリーに変換され、されに視覚的なUIとアクセシビリティツリーに変換される

異なるプラットフォーム間で複数のアクセシビリティAPIをサポートしているブラウザもあれば、特定のアクセシビリティのみをサポートしているブラウザもある。しかし、少なくとも1つのネイティブアクセシビリティAPIをサポートするブラウザはセマンティックの情報構造ツリーを公開するためのメカニズムを持っている。このAPIの目的のため、実装の詳細は気にせずそれらのAPIを参照する。

ネイティブHTMLをアクセシビリティツリーにマッピングする

ネイティブHTML要素はアクセシビリティAPIに暗黙的にマップされる。例えば <img> 要素は自動的に image ロールを持つアクセシビリティノードにマップされ、 alt 属性(があれば)によってラベリングされる。

<img>ノードが、ページ、またアクセシビリティノード上の image として変換される

ARIA

また、ARIAを利用することで開発者が属性によって要素に注釈をつけ、要素のデフォルトのロールやセマンティックプロパティを上書きすることができるが、アクセシビリティアクションは公開できない。

<div role=checkbox aria-checked=true> は視覚的なUIとDOMノードに変換される

どちらの場合も、DOMノードとアクセシビリティツリー内のノードは1対1で対応しており、対応するアクセシビリティノードのセマンティクスにたいする最小限の細やかな制御ができる。

付録: AccessibleNode の命名

仮想アクセシビリティツリー内の一つのノードを示すクラスの名前を AccessibleNode とした。

この名前を選ぶ際、簡潔さと明確さ、そして普遍性の間のバランスを取ろうとした。

以下に、真剣に提案されたすべての名前のそれぞれの長所と短所を簡潔にまとめた。

まだ以下の名前への投票や違う名前の提案は歓迎しているが、まずは既存の提案とその懸念点を慎重に考慮してほしい。すでに大筋で合意には至っており、完璧な命名にしようとするよりはむしろ世に出すよう努めていきたい。

提案された名前 長所 短所
Aria 短い; すでにアクセシビリティと関連している ARIAは仕様の名前であり、アクセシビリティツリー内のノードの名前でないため混乱する
AriaNode 短い; すでにアクセシビリティと関連している AOMはARIA属性のみを公開することを暗示していて制限的すぎる
A11ement 短い; Element に近い 読みにくい; 数字が含まれている; 要素と必ずしも関連付けられていない; 分かりにくい
A11y 非常に短い; DOMの関連団体について主張しない 読みにくい; 数字が含まれている; 分かりにくい
Accessible 一つの完全な単語である; タイプが難しくない 名詞ではない
AccessibleNode 非常に明確; 読むのが簡単 長い; 混乱する可能性がある (他の Node はアクセシブルではない?)
AccessibleElement 非常に明確 さらに長い; 混乱する (他の Element はアクセシブルではない?)
AccessibilityNode 非常に明確 非常に長い; 初めてのときに ‘accessibility’ を正確にタイプできる人はこの星にいない
AccessibilityElement 非常に明確 笑えるほど長い; まだ ‘accessibility’ とタイプしないといけない