Extended HTML
WAI-ARIAとMicrodataでHTMLを拡張する

@Frontend Conference 2016

Soichi Masuda / @masuP9

自己紹介

私の写真

  • 桝田 草一
  • フロントエンドエンジニア兼ディレクター
  • @デジパ株式会社
  • 東京の会社所属、大阪でリモートワーク

はじめに

2014年10月28日、HTML5勧告

  • section
  • article
  • nav
  • header
  • footer
  • time
  • aside
  • main
  • video
  • audio
  • canvas
  • data

etc...

いっぱい要素増えましたね。

これで全てがセマンティクスになって
マシンリーダブルで アクセシブルで
サーチエンジンオプティマイズドに

ならない
(あたりまえ)

もっとセマンティクスで色々したい

どうすれば...

! ... 新しい要素作ろう

つらい記憶

  • html5shiv.js
  • timeなくなってしまうん?
  • hgroup...

ブラウザの対応も早くなってきましたが、それでも大変

属性があるじゃないか

属性でHTMLを拡張してあれやこれやしよう

WAI-ARIAでHTMLを拡張して
アクセシビリティを向上させる

WAI-ARIAとは

W3C内の
Web Accessibility Initiative
が策定した
Accessible Rich Internet Applications
に関する仕様です。

WAI-ARIA 1.0は2014年3月20日勧告、現在はWAI-ARIA1.1がWorking Draft

WAI-ARIAは何をする

ウェブコンテンツやアプリケーションの
アクセシビリティを向上する目的で

  • (ホスト言語に)不足しているセマンティクスを拡張し
    アクセシビリティAPIを通じて支援技術に伝える
  • フォーカス制御を拡張する

HTMLなアプリケーションに
不足しているセマンティクス

  • 役割 role="menuitem"
  • ステート aria-hidden="true"
  • プロパティ aria-haspopup="true"

JavaScript

aria-*,role

DOM

アクセシビリティAPI
(アクセシビリティオブジェクトツリー)

支援技術(スクリーンリーダーなど)

WAI-ARIA実装例

WAI-ARIA属性を可視化するCSSを当てて
Webアプリケーションを見てみましょう

WAI-ARIAの実装

役割 role

要素の役割を定義

メニュー
<ul role="menu">
<li role="menuitem"><a href="#">環境設定</a></li>
<li role="menuitem"><a href="#">アカウント</a></li>
<li role="menuitem"><a href="#">ヘルプ</a></li>
</ul>

読み上げ例:メニュー3項目

ステート, プロパティ aria-*

要素の状態や性質を表す

動的に実装することが多い

とにかくsetAttribute

そしてsetAttribute

<button id="demo1-button">開くボタン</button>
<p id="demo1-content">そして<code>setAttribute</code></p>
var button  = d.getElementById('demo1-button'),
    content = d.getElementById('demo1-content');
// 初期化
content.setAttribute('aria-hidden', true);
button.setAttribute('aria-controls', 'demo1-content');
button.setAttribute('aria-expanded', false);
// クリック時
button.addEventListener('click', function(){
  content.setAttribute('aria-hidden', false);
  this.setAttribute('aria-expanded', true);
});
#demo1-content[aria-hidden="true"] { display: none; }

実装の注意点
from Using WAI-ARIA in HTML

  • ネイティブの要素が使えるならそちらを使う
  • ネイティブのセマンティクスを変更しない
ネイティブの要素が使えるならなるべくそちらを使う
<div role="button">ボタン</div>

<button type="button">ボタン</button>

既存のHTMLを変更する場合はCSSなどの変更点が多く難しいことがあります。
その時はroleをつけるだけでも意味があります。

ネイティブのセマンティクスを変更しない
<h2 role="button">Q.見出しを押すと本文が開きますか</h2>
<p>A.本文だよ。見出しを押すと本文は開くよ。</p>

見出しのセマンティクスが上書きされてしまう

<h2><button>Q.見出しを押すと本文が開きますか</button></h2>
<p>A.本文だよ。見出しを押すと本文は開くよ。</p>
デフォルトの暗黙のARIAセマンティックとの衝突

HTML5.1から参照しているARIA in HTML(WD)では…

著者は、強いネイティヴセマンティックと衝突するまたは与えられるHTML要素のデフォルトの暗黙のARIAセマンティックと等価である場合を除いた、[wai-aria-1.1]で説明される要求にしたがって、HTML要素のARIA roleおよびaria-*属性を使用してもよい。

via ARIA in HTMLの使用に対するウェブ開発者の要件 - ARIA in HTML 日本語訳

ウェブ開発者は、HTMLにおけるARIA属性の使用に対する文書適合性の表に示されるセマンティックと矛盾する方法でARIA roleおよびaria-*属性を使用してはならない。

via ARIA in HTMLの使用に対する文書適合性要件 - ARIA in HTML 日本語訳
使用すべきでない
<header role="banner"> ~~ </header>
<main   role="main"> ~~ </main>
<footer role="contentinfo">  ~~  </footer>

<header> ~~ </header>
<main> ~~ </main>
<footer>  ~~  </footer>

ただし、ARIA in HTMLは、HTML5.1が参照する
Working Draft で少し先の話。

ブラウザによっては、まだmainrole="main"を持ってないケースもあるので、対象ブラウザ次第。

HTMLも進化していく

時間とともに、ホスト言語は、今のところWAI-ARIAを使ってのみ宣言できるオブジェクトのセマンティックを提供するために進化していくことが予想される。( ~ 中略 ~ )
所定の機能に対するネイティヴセマンティックが使用可能になる場合、著者は、ネイティヴ機能を使用し、その機能のWAI-ARIAの使用を中止することが適切である。しかし、レガシーコンテンツは WAI-ARIAを使用し続けるかもしれないので、WAI-ARIAをサポートするユーザーエージェントの必要性が残っている。

1.4 WAI-ARIAとホスト言語の相互進化
Accessible Rich Internet Applications (WAI-ARIA) 1.1 日本語訳

ライブラリ/フレームワークから使う

  • Bootstrap4 ~
    (3)も対応プラグインあり
  • Foundation6 ~
    ※全てのコードスニペットが対応とのこと
  • AngularJS
    ngAreaモジュールあるけど完璧じゃない。
    ※属性変更ツラい
  • React
    ※属性変更しやすそう(相性良さそう)

デバッグ

メタ情報なので視覚的にデバッグするのツラい
聴覚(スクリーンリーダー)も慣れてないとツラい

ブラウザ上なら Dev tool か拡張機能

アクセシビリティAPIを見る
静的に確認する

aViewer (Windowsのみ)

CSS属性セレクタを用いて状態とスタイルを紐付ける

状態と見た目が統一され、デバッグもしやすくなる

[aria-hidden="true"] { display: none; }
.button,
[role="button"] {
  ~~~~
}

※HTMLとCSSが密結合

※コンポーネント状態がaria-*で表せる場合に限られる

属性値を見える化する

display-wai-aria.css

最後はスクリーンリーダーで確認を

要件にあればもちろん対象のもので

MacはVoiceOver、WindowsはNVDAが始めやすい

WAI-ARIAまとめ

  • アクセシビリティのためのマークアップ言語拡張仕様
  • ネイティブのセマンティックスを補う補助輪
    要らなくなったら外す準備をしよう
  • デバッグはツールを使って効率化しよう

参考図書

コーディングWebアクセシビリティ
WAI-ARIAで実現するマルチデバイス環境のWebアプリケーション

MicrodataでHTMLの
セマンティクスを拡張する

それ(HTML)の仕様です

5 Microdata - HTML Standard


MicrodataはHTMLコンテンツに
メタ情報を追加するための仕様

基本文法

  • itemscopeでアイテムを作り、
  • itemtypeで語彙を定義し、
  • 子要素にitempropを付与してプロパティを追加していく
<div itemscope="itemscope" itemtype="http://schema.org/Person">
<p>私の名前は<span itemprop="name">桝田 草一</span>です。</p>
</div>

schema.orgのPerson語彙を使ってPerson型のitemを作る。
nameプロパティの値は"桝田 草一"

要素内のtextContentがプロパティの値

<p><span itemprop="name"><a href="/?user=daniel" target="_blank">Daniel</a></span>.</p>

"name": "Daniel"

aの場合は、hrefが、
imgの場合はsrcが値となる。

<img itemprop="image" src="http://other.site/img/photo.jpg" alt="写真" />

"image": "http://other.site/img/photo.jpg"

data, metervalue
timeならdatetimeが値となる。

<time itemprop="birthday" datetime="1985-02-07">1985年02月07日</time>

"birthday": "1985-02-07"

なんかいいことあるの?

マシンリーダブル

検索エンジンリーダブルなメタデータ

リッチスニペット

CTRを向上したり

最近話題のアレ(AMP)にも必要

発表後追記:AMPで必要なのはMicrodataじゃなくてschema.orgをJSON-LDでした。すみません、すみません。

WebサイトのAPI化

Microdata DOM APIを使って
ページ内の構造化データを処理

var events = document.getItems('https://schema.org/Event');

例:Google Shopping

<div itemscope itemtype="http://schema.org/Product">
  <span itemprop="name">Google Nexus 7</span>
  <meta itemprop="gtin14" content="00886227537143" />
  <meta itemprop="sku" content="abc123" />

  <div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
    <meta itemprop="priceCurrency" content="USD" />$
    <span itemprop="price">229.95</span>
    <meta itemprop="itemCondition" itemtype="http://schema.org/OfferItemCondition" content="http://schema.org/NewCondition"/>New
    <meta itemprop="availability" content="http://schema.org/InStock"/>Available online
  </div>
</div>
Google ショッピングでの microdata の使用 - Google Merchant Center ヘルプ

実装の注意点

Microdata ≠ schema.org ≠ Google Rich Snippets

  • MicrodataはHTMLの記法
  • schema.org は語彙
  • Google Rich Snippetsは検索結果のための独自仕様

参照する仕様を間違えずに目的に合わせて実装する

例えば、opeingHours

LocalBusinessRestaurantの営業時間

schema.orgのマークアップ例

The opening hours for a business. Opening hours can be specified as a weekly time range, starting with days, then times per day. Multiple days can be listed with commas ',' separating each day. Day or time ranges are specified using a hyphen '-'.
- Days are specified using the following two-letter combinations: Mo, Tu, We, Th, Fr, Sa, Su.
- Times are specified using 24:00 time. For example, 3pm is specified as 15:00.

http://schema.org/openingHours

ざっくり訳すと

営業時間は1週間の範囲の中から指定することができます。営業日は曜日を表す2文字の組み合わせ(Mo, Tu, We, Th, Fr, Sa, Su)をカンマ区切りで指定し、時間は24時間表記で開始時間-終了時間の形式で指定します。

<time itemprop="openingHours" datetime="Tu,Th 16:00-20:00">Tuesdays and Thursdays 4-8pm</time>
HTMLのtime的にはinvalid

datetimeは一意の時間の指定のみで、曜日の繰り返しは表現できない

じゃあdata
<data itemprop="opneningHours" value="Mo-Fr 09:00-19:00">
Monday-Friday: 9:00 am to 7:00 pm</data>
Structured Data Testing Toolでのテスト結果
なぜなのか
困ったときのmeta
毎日元気に営業中!!!!!!!!!!
<meta itemprop="openingHours" content="Mo-Su" />

JSON-LDでいいのでは?

<script id="jsonld" type="application/ld+json">
[
  {
    "@context": "http://schema.org",
    "@type": "BlogPosting",
    "name": "シンタックスハイライトをgoogle code prettifyからhighlight.jsに変えた",
    "url": "http://masup.net/2015/03/change-syntax-highlighter.html",
    "datePublished": "2015-03-19T00:37:31+09:00"
  }
]
</script>

Microdataの安心
基本的にメタ情報とコンテンツが同一


Microdataの苦労
HTMLの可読性が落ちる。
BEM + angular + Microdataなんて日には

CMSから書き出し前提ならJSON-LDの方が◎

語彙の構造とCMSのデータ構造を同一にすると組みやすい。

Microdataまとめ

  • Googleさん周りを中心に必要度は増
  • 目的や環境に応じて、仕様を参照し拡張しよう
ご清聴ありがとうございました