role属性とaria-*属性(WAI-ARIA)について【HTML5 Advent Calendar 2012 Day 9】

このエントリーは、HTML5 Advent Calendar 2012 9日目の記事です。

この回では、HTML5で使えるようになった(正確に言うと、HTML4/XHTML1でも使えるといえば使えます) roleコンテンツ属性(以後role属性)とaria-*コンテンツ属性(以後aria-*属性)について書きます。

role属性とaria-*属性

role属性とaria-*属性は、HTML5から登場したものではなく、WAI-ARIAで定義されている仕様です。

WAI-ARIA

WAI-ARIAとは、Web Accessibility Initiative Accessible Rich Internet Applicationsの略で、 どういった仕様かというと、以下のWAI-ARIA Overviewから引用です。

WAI-ARIA, the Accessible Rich Internet Applications Suite, defines a way to make Web content and Web applications more accessible to people with disabilities. It especially helps with dynamic content and advanced user interface controls developed with Ajax, HTML, JavaScript, and related technologies.

日本語訳にすると、WebコンテンツおよびWebアプリケーションを障がいのあるユーザにとってよりアクセシブルにするもので、 HTMLやAjaxやJavaScriptなどで作られたRIA(Rich Internet Applications)にフォーカスしたものです。

仕様的には、要素にロール(役割)とステート/プロパティ(状態)を追加をすることがWAI-ARIAです。

○○○もどきの実装

HTMLというのは、基本的には、意味を持っています(特に意味をなさない要素もありますが)。その意味というのが「見出し」や「リスト」です。

私たちは、それらのHTMLを使ってUIなどの実装を行っています。例えば、タブパネルを実装するときは、div要素やul要素などを使うでしょう。 当然ながら、この場合だとHTMLの意味としては、リストやグループという意味しか成しません。つまり私たちは「これはタブパネルのつもり」として実装しているわけです。 また、どのタブが選択されているのか、どのパネルが表示されているのかも視覚的には分かっても機械的には知ることができません。

しかし、WAI-ARIAを使うことで、この「タブパネルもどき」のHTMLが「タブパネル」のロール(役割)を与え、どのタブが選択されているか、 どのパネルが表示・非表示なのかというステート/プロパティ(状態)をブラウザに知らせてくれるのです。

WAI-ARIAを用いた実装例

ここより、「ボタン」、「ページのリージョン」、「タブパネル」を例に実際にWAI-ARIAを用いた実装例です。

ボタン

ここでは、CSSでボタンのようにみせるという前提ですが、下記図のようなボタンについて実装を例に挙げます。

HTMLは仮に、以下のようにします。

<span id="btn">
ボタン
</span>

セマンティックなマークアップを心がけるならば、ボタンのマークアップは、button要素やinput要素を用いるべきです。 そうでなければ、WCAG 2.0/JIS X 8341-3:2010の達成基準4.1.2 プログラムが解釈可能な識別名・役割及び設定可能な値:を満たせない可能性がでてくるからです。

また、WCAG2.0技術書に、不適合事例として、F59: 達成基準 4.1.2 の不適合事例 - スクリプトを用いて、HTMLのdiv要素又はspan要素をユーザーインタフェースのコントロールにしているが挙げられていることから、すべきではありません。 しかし、WCAG2.0の解説書には、F59に対して以下のような注記があります。

注記: この不適合事例は、将来的に DHTML ロードマップ (WAI-ARIA) の実装方法を用いて問題が解決されるかもしれない。

どうしてもspan要素(button要素やinput要素以外のHTML要素)で実装しなければならないような場合があれば、以下のように実装すればよいでしょう。

<span id="btn" role="button" tabindex="0" aria-pressed="false">
ボタン
</span>

id属性以外の属性の解説をします。

  • span要素は特に意味を持たないHTML要素です。当然ながらこのままだと「ボタン」と認識してくれません。 そのため「ボタン」という認識をさせるために、ボタンの役割をするrole="button"を追加します。
  • このままでは、キーボードで操作しているユーザーには、 フォーカスがあたらないので、このボタンを押すことができません。フォーカスがあたるようにtabindex属性を追加します。
  • 押した後に何をするかにもよりますが、押したという状態を伝える必要がある場合には、aria-pressedを追加します。 押していない場合の値は「false」、押した場合の値は「true」にします。

※:これは、現時点で「解決されるかもしれない」なので、WCAG 2.0/JIS X 8341-3:2010の達成基準を満たすことが目的の場合は上記のような実装はせずに、素直にbutton要素やinput要素で実装したほうがよいでしょう。

ページのリージョン

ここでは、ページのリージョンについてです。下記図のようなページがあったとします。

HTML5からはheader要素やfooter要素が追加されたことによって、 「この領域はヘッダー」と明示することができるようになりますが、HTML4/XHTML1の仕様では、div要素でマークアップをするので、 「この領域はヘッダーのつもり」のもどき実装しかできませんでした。しかし、ARIAを実装することで、 こういった場合でもリージョンを明確にすることができるようになります。マークアップは以下のようになります。

<header role="banner">
ヘッダー
<form role="search">
<input type="search" id="search">
<input type="submit" value="search">
</form>
</header>

<nav role="navigation">
<ul>
<li><a href="#">メニュー1</a></li>
<li><a href="#">メニュー2</a></li>
<li><a href="#">メニュー3</a></li>
<li><a href="#">メニュー4</a></li>
<li><a href="#">メニュー5</a></li>
</ul>
</nav>

<div id="main" role="main">
メインコンテンツ
</div>

<footer role="contentinfo">
フッター
</footer>

それぞれのrole属性の解説をします。これらはLandmark Rolesと呼ばれます。

banner
仕様書の説明では、 A region that contains mostly site-oriented content, rather than page-specific content.とあります。 また、Site-oriented content typically includes things such as the logo or identity of the site sponsor, and site-specific search tool. A banner usually appears at the top of the page and typically spans the full width. とあるように、簡単に訳すと「ロゴや独自の検索ツールを含み、そしてページの上部に表示される」ことから、ヘッダーのリージョンで使うことがよいでしょう。また、 HTML5 Editor's Draftのheader要素のところで、 If specified, role must be bannerとあることからheader要素と共に使います。
search

仕様書の説明では、 A landmark region that contains a collection of items and objects that, as a whole, combine to create a search facility.とあります。 検索機能の役割をすることが分かります。

しかし、Landmark Rolesには、form (role)があります。フォームの役割を追加するためのものですが、仕様書を読むと、 For search facilities, authors SHOULD use the search role and not the generic form role. とあるように、検索機能のフォームには、searchを使えと書いてありますので、searchは検索用のフォームに用います。

navigation
仕様書の説明では、 A collection of navigational elements (usually links) for navigating the document or related documents.とあるように、ナビゲーション要素(通常はリンク)の集合ですので、グロナビで使うことがよいでしょう。 また、HTML5 Editor's Draftのnav要素にnavigation roleとあるので、 nav要素で使います。
main
仕様書の説明では、 The main content of a document.とあるようにメインコンテンツのHTML要素に指定をします。
contentinfo

仕様書の説明では、 A large perceivable region that contains information about the parent document.とあります。「親のドキュメントについての情報を含む」....???よく分かりませんね。・・・あいかわらずARIAの仕様書はわかりに(ry

次の説明では、以下のように書かれています。 Examples of information included in this region of the page are copyrights and links to privacy statements. 「コピーライト、プライバシーステートメントへのリンクのリージョンを含む」とあります。これらはフッター領域にあることが多いので、footer要素で使用するものと思います。 また、HTML5 Editor's Draftのfooter要素にも、 If specified, role must be contentinfoとあるので、footer要素と共に使うことがよいでしょう。

タブパネル

さっきからしつこい(謎)タブパネルについてです。見た目は下記図のような感じとします。

HTMLは以下のようにします。タブ部分をul要素、タブパネル部分をdiv要素での実装です。

<div id="tab">

<ul>
<li id="tab1">
<a href="#tabpanel01">タブ1</a>
</li>
<li id="tab2">
<a href="#tabpanel02">タブ2</a>
</li>
<li id="tab3">
<a href="#tabpanel03">タブ3</a>
</li>
</ul>

<div id="tabpanel01">
Lorem Ipsum is simply dummy text...
</div>

<div id="tabpanel02">
Lorem Ipsum is simply dummy text...
</div>

<div id="tabpanel03">
Lorem Ipsum is simply dummy text...
</div>

<!-- /tab --></div>

このままだと以下のような問題があります。

  • タブとタブパネルと認識されない
  • どのタブが選択されているか分からない
  • どのタブパネルが表示・非表示なのか分からない
  • タブとタブパネルの関係性

上記の問題を解決すべくARIAを用いたタブパネルの実装は以下のようになります。

<div id="tab">

<ul role="tablist">
<li id="tab1" role="tab" aria-selected="true" aria-controls="tabpanel01">
<a href="#tabpanel01">タブ1</a>
</li>
<li id="tab2" role="tab" aria-selected="false" aria-controls="tabpanel02">
<a href="#tabpanel02">タブ2</a>
</li>
<li id="tab3" role="tab" aria-selected="false" aria-controls="tabpanel03">
<a href="#tabpanel03">タブ3</a>
</li>
</ul>

<div id="tabpanel01" role="tabpanel" aria-hidden="false" aria-labelledby="tab1">
Lorem Ipsum is simply dummy text...
</div>

<div id="tabpanel02" role="tabpanel" aria-hidden="true" aria-labelledby="tab2">
Lorem Ipsum is simply dummy text...
</div>

<div id="tabpanel03" role="tabpanel" aria-hidden="true" aria-labelledby="tab3">
Lorem Ipsum is simply dummy text...
</div>

<!-- /tab --></div>

属性の解説をします。

  • タブパネルの役割を成すために、ul要素にtablist、 タブ部分となるli要素にtab、 パネル部分のdiv要素にtabpanelを追加します。
  • タブとなるli要素とパネルのdiv要素は因果関係にあるため、 これらの関係を示すことができるaria-controlsを指定します。値は任意で関連付けとされる要素にはid属性で指定します。
  • li要素にタブの選択状態を伝えるために、 aria-selectedを指定します。 選択された状態のときの値は「true」、選択されていない状態のときの値は「false」を指定します。
  • パネル部分が表示・非表示の状態を伝えるために aria-hiddenを指定します。表示のときの値は「false」、 非表示の値は「true」を指定します。
  • 関連付けのためページ内リンクを実装していますが、タブとパネルを関連付けのために、aria-labelledbyを指定します。値は任意で関連付けとされる要素にはid属性で指定します。

以上がざっくりとサンプルを用いたrole属性とaria-*属性(WAI-ARIAの一部)についてでした。 WAI-ARIAは、2012年12月の段階でCRでまだ勧告まで至ってません。Can I use... Support tables for HTML5, CSS3, etcで見てみるとブラウザのサポート状況もまちまちです。

しかし、まだaria-*属性はそれほど見ませんが、ここ最近は、role属性、特にLandmark Rolesを実装しているのを見ることも多くなってきました。アクセシビリティをより意識をしての実装が増えてきたことなのかもしれません。 この記事でWAI-ARIAについて興味を少しでも持ってもらえたら嬉しいです。それでは、引き続き、HTML5 Advent Calendar 2012をお楽しみください。

WAI-ARIAの関連ドキュメントまとめ