セマンティクスの作り方、これまで、今、そして未来

HTML5 Conference 2018 E3

私たち

@masuP9のプロフィール写真。ますぴーとかかれた木製のバッジの写真 @masuP9(わかり手) 株式会社サイバーエージェント

@o_tiのプロフィール写真。机の上の卵かけご飯 @o_ti(キレ手) 株式会社まぼろし

今日のお話

広義のセマンティクスと今回のセマンティクス

今日はいくつかある未来の中からある一つの未来の話をします

目次

  1. セマンティクスの恩恵
  2. HTML
  3. WAI-ARIA
  4. Accessibility Object Model

セマンティクスの恩恵

ウェブがよりアクセシブルになる。

アクセシブルとは?

  • 近寄りやすいこと
  • 利用しやすいこと

HTML

HTMLというだけで得られるアクセシビリティ

  • どこにいてもページが見られる
  • 様々なOS、ブラウザで閲覧できる
  • テキストがコピーできる
  • 画像が保存できる

※電源とWi-Fiがあれば

HTML5のセマンティクスは

  • HTML4.01の要素の廃止と刷新
  • 「セクショニング」という概念の導入により、見出しの及ぶ範囲が規定された
  • フレージングが強化されて、強調、細目、時間表現が可能になった

etc...

HTMLは宣言的にセマンティクスを定義する

<section>
  <h2>見出し</h2>
  <p><a href="#">パラグラフ</a></p>
  <ul>
    <li>リスト</li>
    <li>リスト</li>
  </ul>
  <button type="button">ボタン</button>
</section>

タグ(要素)によってセマンティクスを
要素の記述順と入れ子によって構造を構築

HTMLの課題

要素名(タグ)に依存する

  • セマンティクスの変更 👉 DOMツリーの変更
  • 新しいセマンティクス 👉 新しい要素
  • 状態やプロパティの欠如

非同期通信で画面が書き換わるアプリケーションなウェブサイトが広まり、現状のHTMLのネイティブセマンティクスでは足りなくなっている

HTMLも進化を続ける

dialog要素

モーダルなダイアログをHTML要素で表現できる

<button id="confirm">確認</button>

<dialog id="privacy-policy">
  <h1>プライバシーポリシー</h1>
  <p>同意せよ</p>
  <button id="agree">同意します</button>
</dialog>

hgroup要素

副次的な見出し/キャッチコピー/スローガンを
マークアップできる。

<section>
<hgroup>
  <h1>deisui_html_radio #sp1</h1>
  <h2>〜マークアップは裏切らない〜</h2>
</hgroup>

<p>我々はJSフレームワークと戦い、マークアップ共和国を作りました。</p>
</section>

まだ見ぬ要素も追加される可能性は十分ある

HTML以外のセマンティクスと言えば?

  • XHTML
  • Microdata
  • RDF
  • Schema.org

etc...

よくあるMicrodataで提供されたセマンティクス

  • パンくずリスト(ページ階層情報)
  • 記事リスト(カテゴリトップから見て、そのカテゴリに属する記事ものの一覧)
  • レビュー情報
  • レシピ情報

確かに現在のHTMLにないセマンティクスを提供するが、
これらはどちらかというとデータ構造を俯瞰したものを提供する力が強い。

そのウェブページ上で利用するというよりは、外部ツール(検索エンジン)がパースしてそのウェブページの外で使われている。

やりたいのはそのウェブページ自体のセマンティクスの強化なんだよ!!!

そこでWAI-ARIA

アプリケーションなウェブページをアクセシブルにするため、HTML(ホスト言語)のセマンティクスを補強するための仕様

特徴

  • 属性によってセマンティクスを付与
  • 役割状態プロパティを持てる
role
役割
aria-*
状態、プロパティ
<ul role="tree" aria-label="menu tree">
  <li role="treeitem" aria-selected="true">...</li>
  <li role="treeitem" aria-selected="false">...</li>
</ul>

役割 : role

<ul role="tree"></ul>

これはツリーウィジェットである

状態 : ステート

<li role="treeitem" aria-selected="true">...</li>

このツリーアイテムは選択されている/されてない

プロパティ

<ul role="tree" aria-label="menu tree"></ul>

このツリーウィジェットの名前プロパティはmenu treeである

関係のセマンティクス

DOMツリーに依存しない関係性を定義できる。

パスワードは8文字以上必要です。

<label>パスワード:
  <input type="password" aria-describedby="description" />
</label>
<p id="description">パスワードは8文字以上必要です。</p>

WAI-ARIAのユースケース

タブ

同じ表示領域で内容が切り替わるウィジェット

  • role="tablist"
  • role="tab"
  • role="tabpanel"
  • aria-selected
  • aria-hidden

WAI-ARIAなし

<nav>
  <ul>
    <li>
      <a href="#tabItem1">越智</a>
    </li>
    <li>
      <a href="#tabItem2">桝田</a>
    </li>
  </ul>
</nav>
<div>
  <div id="tabItem1">キレ手</div>
  <div id="tabItem2">わかり手</div>
</div>

WAI-ARIAあり

<nav>
    <ul role="tablist">
      <li role="presentation">
        <a href="#tabItem1" role="tab" aria-controls="tabItem1" aria-selected="true" id="tabBtn1">越智</a>
      </li>
      <li role="presentation">
        <a href="#tabItem2" role="tab" aria-controls="tabItem2" aria-selected="false" id="tabBtn2">桝田</a>
      </li>
    </ul>
  </nav>
  <div>
    <div id="tabItem1" role="tabpanel" aria-describedby="tabBtn1" aria-hidden="false">キレ手</div>
    <div id="tabItem2" role="tabpanel" aria-describedby="tabBtn2" aria-hidden="true">わかり手</div>
  </div>

ライブリージョン

更新される領域であることを支援技術に伝える

  • チャット
  • 株価表示ウィジェット
  • スポーツのテキスト実況
  • フォームの入力エラー

etc...

コメント欄

<div role="log" aria-live="polite">
  <ol>
    <li>魔界合宿</li>
    <li>「人はすぐ死ぬ」</li>
    <li>伊東家のこじらせ</li>
    <li>マスみがある</li>
  </ol>
</div>
<div role="log" aria-live="polite">
  <ol>
    <li>魔界合宿</li>
    <li>「人はすぐ死ぬ」</li>
    <li>伊東家のこじらせ</li>
    <li>マスみがある</li>
    <li>例え話下手くそ選手権優勝</li> <!-- New -->
  </ol>
</div>

ホスト言語との相互進化

WAI-ARIAはホスト言語と相互に進化していく

ネイティブセマンティクスの尊重

WAI-ARIAは補強するもので代替では無い

😠DON'T
😍DO

これらの付与されたセマンティクスはどのようにユーザー(支援技術)に伝わるか

アクセシビリティAPI

OSが支援技術にセマンティクスなどの
情報を伝えるAPI

ブラウザがレンダリングしているコンテンツと
セマンティクスをアクセシビリティAPIの
オブジェクトに変換して支援技術に伝える

ブラウザ HTML DOM CSS WAI-ARIA JS + + OS アクセシビリティ API 支援技術
ブラウザがコンテンツやセマンティクスを支援技術に伝えるまで

WAI-ARIAの課題

セマンティクスがDOMに依存

要素に属性として付与しないといけない

  • DOMノード(要素)がないUIに関与できない
    (e.g. canvasの中のUIなど
  • 関係属性から要素を参照する場合、要素に識別用のidが必要
  • アクセシビリティツリーに影響を及ぼすが、結果どうなったかを確認できない

Accessibility Object Model

アクセシビリティAPIに変換されうるセマンティクスをモデルとして定義しJavaScriptから操作・探索可能にしたもの(ないしは提案)

IDLインターフェースから
ARIA属性を反映する

const tree = document.createElement('ul');
tree.role = 'tree';
tree.ariaLabel = 'menu tree';

関係のセマンティクスも

const desc = document.querySelectorAll('.tree-desc');
tree.ariaDescribedBy = [...desc].map(el => el.id).join(' ');

Demo

See the Pen Demo: AOM Reflecting ARIA attributes by masuP9 (@masuP9) on CodePen.

Out-of-date syntax

tree.accessibleNode.role = "tree";
tree.accessibleNode.label = "menu tree";

DOMに反映されないARIAを付与する

  • IDLでは要素上のDOMへ属性を反映のみ
  • 参照するにもidが必要

さっきのこれ

const desc = document.querySelectorAll('.tree-desc');
tree.ariaDescribedBy = [...desc].map(el => el.id).join(' ');

こうしたい!

const desc = document.querySelectorAll('.tree-desc');
tree.ariaDescribedByElements = [...desc];

ユースケース Web Componentsのデフォルトセマンティクスを定義する

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

Web ComponentsでのshadowRoot問題

支援技術からのイベントに対応

支援技術が起こすイベントをDOMのイベントに
ルーティングしハンドリングすることができるようにする。

<button type="button" onclick="alert('click!')">button</button>

現状、支援技術のイベントをルーティングするにはDOMのイベントが足りない。

role="slider"の増加/減少イベントなど

<input type="range" />要素上のみハンドリング可能

(動かない)Demo

See the Pen Demo: Listen for input events from AT by masuP9 (@masuP9) on CodePen.

Out-of-date syntax

element.accessibleNode.addEventListener('accessibleclick', function);
element.addEventListener('accessibleclick', function);

プライバシーの問題

Virtual Accessibility Node

canvasなどで作られたUIに対して仮想のアクセシビリティノードを付与する。

const canvas = document.getElementById('canvas');
canvas.attachAccessibleRoot();

const table = canvas.accessibleRoot.appendChild(new AccessibleNode());
table.role = 'table';

Demo: Build virtual accessible nodes out of date syntax

See the Pen Demo: Build virtual accessible nodes out-of-date syntax by masuP9 (@masuP9) on CodePen.

Screen shot Virtual Accessibility Tree(Chrome 70)
Accessibility Treeインスペクタのスクリーンショット。Canvasを起点に heading と list, listitem がテキストノードを持ってAccessibility Treeに表示されている。

ここでもプライバシーの問題?

Query Computed Accessibility Tree

計算されたアクセシビリティツリーを確かめる。

const tree = document.createElement('ul');
tree.role = 'tree';
window.getComputedAccessibleNode(tree).then(result => {
  console.log(result.role); // 👉 'tree';
});

非同期で取得する

Demo

See the Pen Demo: Query computed Accessible Tree table display: block; table by masuP9 (@masuP9) on CodePen.

Use case

  • アクセシビリティツリーの自動テスト
  • ブラウザ拡張機能による支援技術

AccessibleNode はどうなった?

当初はDOMのElementに関連付けられたAccessibleNodeからプロパティを
読み書きする方針だった

以下のような問題があり、AccessibleNode ではなく簡素なAPIへの提案へ以降

  • パフォーマンス
  • アクセシビリティツリー計算方法の標準化
  • ARIAプロパティとAccessibleNodeプロパティの優先順位
  • アクセシビリティツリーは、レンダリングツリーにARIAなどが反映されて計算される。
  • 計算済のアクセシビリティツリーを取得するには多くの計算が必要。
  • アクセシビリティツリーの計算方法も各ブラウザによって少しずつ異なる...
element.accessibleNode.role = 'tree';
console.log(element.accessibleNode.role) // 本当に 'tree' 🤔

単純な参照では無い。

書き込みと読み取りを共通化しない

element.role = 'tree';
window.getComputedAccessibleNode(element).then(result => {});

Can I use AOM

Chrome 70 Firefox NB*1 Safari TP*2
Reflect ARIA attributes Yes*3 *4 No No
Listen for input events from AT No No No
Build virtual accessible nodes Yes *5 No No
Query computed accessibility tree Yes No *6 No
  1. 65.0a1 (2018-11-23) (64 bit)
  2. Release 70 (Safari 12.1, WebKit 13607.1.13)
  3. 一部古い記法の対応が残る
  4. バグが多い😭
  5. 古い記法による対応
  6. element.AccessibleNodeのみ存在

まとめ