Webアクセシビリティにおける、ロール（role）の解説

アクセシビリティを考慮したWeb開発の話題で、しばしば **「ロール（role）」** というものが登場します。 `role="button"` のような **`role`属性** として紹介されていることもあります。

ロールは、Webアクセシビリティでとても重要な概念なのですが、わかりやすい解説記事があまり多くない印象です。一方で「role属性を使えばアクセシビリティが向上する」という誤解を招きそうな内容のものもちらほらと存在しており、それを信じて誤った使い方をすることで、かえってアクセシビリティを下げかねない状態になっています。

そこでこの記事では、**`role`属性ではなくロールそのもの** についての解説をしたうえで、ロールを適切にする方法のひとつとして、`role` 属性の立ち位置についても解説します。

より広く詳しい内容については、Qiitaに書いた記事「[role 属性とは、aria-* 属性とは、WAI-ARIA とは、いったい何なのか、いつ使うべきなのか](https://qiita.com/ymrl/items/6c9c059208ea11e6d7bc)」や、共著書「[Webアプリケーションアクセシビリティ](https://webapp-a11y.com/)」も参照してください。

## この記事で伝えたいこと

- ロールは、支援技術に対して画面上の要素が何であるかを伝えるものです
- HTML要素は暗黙的にロールを持つため、ほとんどの場合で `role` 属性を使う必要はありません
- `role`　属性を使用せざるを得ないケースもありますが、仕様の理解と入念な動作確認が必要となるため、原則として避けるべきです


## 前提: スクリーンリーダー、支援技術、WAI-ARIA

Webアクセシビリティの話題には、よく **スクリーンリーダー** という、主に視覚障害者が使用する、画面に表示されているものを読み上げるツール（機能）が登場します。スクリーンリーダーを使うことで、画面を視覚的に見ることができなくても、パソコンやスマートフォンを操作できます。

スクリーンリーダーのように、心身の障害などにより不便がある場合にその補助をするソフトウェアやハードウェアは、「**支援技術**」と呼ばれます。

Webアクセシビリティはあらゆる人がWebコンテンツを利用できることを目指しますが、そのなかには支援技術のユーザーも含まれます。Webコンテンツと支援技術がどう連携するべきなのか、どうWebコンテンツを作れば支援技術から利用できるようになるのかの技術仕様を定めているのが 「**WAI-ARIA**」 です。

今回解説する「ロール」も、WAI-ARIAの仕様に登場する概念です。また、role属性も、WAI-ARIA仕様書のなかで定義されています。

支援技術には様々なものがありますが、スクリーンリーダーはWAI-ARIAに強く依存する特徴があります。なぜなら、Webコンテンツの情報のほとんどが視覚的に表現されている以上、スクリーンリーダーはそのすべての情報をユーザーに伝え、操作もスクリーンリーダーを通じて行わなければなければならないからです。

そのため、WAI-ARIAの利用例や失敗例の説明にはスクリーンリーダーがしばしば登場します。この記事も例外ではありません。

## スクリーンリーダーが読み上げるのは、画面の上の文字だけではない

たとえば、Webページ上に、以下のHTMLで表されるような構造があったとします。よくあるコーポレートWebサイトの冒頭をイメージしています。

```html
<h1>ホゲフガ株式会社</h1>
<nav>
  <ul>
    <li><a href="/about">会社概要</a></li>
    <li><a href="/services">事業内容</a></li>
    <li><a href="/contact">お問い合わせ</a></li>
  </ul>
</nav>
```

なにもスタイルシートをあてたりしていない状態で表示すると、以下の画像のようになります。

![大きな文字で「ホゲフガ株式会社」と書かれた下に、箇条書きのリンクで、「会社概要」「事業内容」「お問い合わせ」が並んでいる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22333/1a38a655-3850-5223-0d9a-f7ad4ac96b6f.png)

スクリーンリーダーによって読み上げられ方は違いますが、概ね以下のような内容が読み上げられます。

> *見出しレベル1* ホゲフガ株式会社
> *ナビゲーション* 
> *リスト 3項目*
> *行頭記号* *3の1* *リンク* 会社概要
> *行頭記号* *3の2* *リンク* 事業内容
> *行頭記号* *3の3* *リンク* お問い合わせ

このように、画面に表示されている文字だけでなく、「この部分は見出しである」「この部分はナビゲーションである」「この部分はリストである」「リストには何項目ある」「いまリストの何個目の項目を読んでいる」といった情報も読み上げられます。このような情報がなければ、スクリーンリーダーのユーザーはページがどういう構成になっているのか、理解することができません。

スクリーンリーダーは、表示されている文字だけでなく、「その部分が何であるか」「その部分がどんな状態か」といった情報も読み上げます。そのために必要となるのが、WAI-ARIAに規定されている「**アクセシビリティツリー**」の情報です。

## アクセシビリティツリー

アクセシビリティツリーは、ブラウザが支援技術に向けて生成する、Webページ上のUIをツリー構造で表現したものです。「アクセシビリティオブジェクトモデル（Accessibility Object Model: AOM）」という呼ばれ方もされます。

UIを構成する要素には、「見出しである」「リンクである」「チェックボックスである」というふうに、「それぞれが何であるか」という情報が必要不可欠です。また、「見出しのレベルが1である」「チェックボックスがチェックされている」というふうに、属性や状態の情報をもつものもあります。アクセシビリティツリーは、こういった支援技術に伝わるべき **意味（セマンティクス）** をツリー構造としたものです。

この、 **アクセシビリティツリーの上にある「これが何であるか」の情報こそが「ロール（role）」です**。先述の読み上げ方の例では、以下のようなロールの情報が読み上げられていました。

- 見出し: `heading` ロール
- ナビゲーション: `navigation` ロール
- リスト: `list` ロール
- リスト項目: `listitem` ロール（「3の1」などの読み上げに現れています）
- リンク: `link` ロール


アクセシビリティツリーには、ロールの他にもプロパティ（property）とステート（state）の情報が含まれます。これらによって支援技術へ伝えられる意味（セマンティクス）を「WAI-ARIAセマンティクス」と呼びます。

なお、ブラウザが構築しているアクセシビリティツリーは、ブラウザの開発者ツールで閲覧することができます。

- [Chrome DevTools のフル ユーザー補助ツリー](https://developer.chrome.com/blog/full-accessibility-tree?hl=ja)
- [Firefoxの開発者ツールにアクセシビリティインスペクターが追加](https://www.mitsue.co.jp/knowledge/blog/a11y/201804/16_1753.html)

## 暗黙のロール

先述の例では、特別なことをしていない普通のHTMLでも、スクリーンリーダーは「見出し」「ナビゲーション」「リスト」などのロールに基づいた読み上げをすることができていました。

アクセシビリティツリーは、DOMの内容と一部のCSSによるスタイルの情報から生成されます。このとき、標準的なHTMLの機能から読み取れる情報[^html]は、アクセシビリティツリーにもそのまま反映されます。先述の例では、`<h1>` `<nav>` `<ul>` `<li>` `<a>` といった要素を使ったおかげで、これらが持つであろうロールがアクセシビリティツリーに反映されていました。

[^html]:WAI-ARIAはホスト言語をHTMLに限定しませんが、わかりやすさを重視して、ほとんどの場合で意識されるHTMLにのみ言及しています。

この、なにもしなくても（黙っていても）HTMLからアクセシビリティツリーに反映される情報を「 **暗黙のWAI-ARIAセマンティクス** 」と呼びます。ロールの場合は「**暗黙のロール** 」と呼びます。

暗黙のWAI-ARIAセマンティクスがあるおかげで、HTMLを書く人は特にアクセシビリティツリーのことを意識することなく、支援技術からでも充分便利に使えるWebコンテンツを作ることができます。


## `role`属性による明示的なロールの指定

WAI-ARIAには、アクセシビリティツリー上の情報を明示的に指定するための属性が定義されています。ロールを明示的に指定する場合には `role` 属性を使用します。`aria-` のプレフィックスのついた属性を使うことで、プロパティやステートを変更することもできます。

```html
<!-- これは <h1>ホゲフガ株式会社</h1> と書いてるのと同じ -->
<div role="heading" aria-level="1">ホゲフガ株式会社</div>
```

これらの属性を使うことで、HTML要素の暗黙のWAI-ARIAセマンティクスを上書きし、アクセシビリティツリーを制御することができます。ただし、これはやり方を間違うと、支援技術からのアクセシビリティを **破壊してしまう** ため、**不用意にやるべきことではありません** 。

アクセシビリティツリーを書き換えると、その要素が元々持っていたWAI-ARIAセマンティクスは失われます。たとえばテーブルセルの `<td>` 要素に `role="button"` を付けたところ、暗黙の `cell` ロールが失われ、スクリーンリーダーが見出しセルの `<th>` 要素を参照した読み上げをしなくなったり、テーブル内での上下左右のセルへの移動がうまくいかなくなったりします。

また、WAI-ARIAのロールやステートやプロパティは、仕様として利用できる組み合わせが決まっていたり、ロールによっては必須のプロパティが存在するようなものもあります。さらに、WAI-ARIAの提供する属性がどのように効力を発揮するかは、ブラウザや支援技術の実装状況や実装方針にも依存します。仕様書で存在が触れられているからといって、支援技術が解釈できるとは限りません。 使いこなすには **仕様書を読み解き、多様なブラウザや支援技術でテストする覚悟** が求められます

WAI-ARIAの具体的な使い方を解説している[ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/) の [Read Me First](https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/) ページでは、「No ARIA is better than Bad ARIA（悪いARIAよりもARIA無しのほうが良い）」として、この問題に対して強く警告しています[^bad]。

[^bad]: 「No ARIA is better than Bad ARIA（悪いARIAよりもARIA無しのほうが良い）」として書かれている内容の、日本語での解説は、「[role 属性とは、aria-* 属性とは、WAI-ARIA とは、いったい何なのか、いつ使うべきなのか](https://qiita.com/ymrl/items/6c9c059208ea11e6d7bc)」にあります。この記事では省略します。

### `role` 属性を使わざるを得ないケース

**多くの場合、`role`属性を使ってロールを書き換える必要はありません** 。Webコンテンツの上で日常的に見かける、または私たちがデザインしたり実装したりしている大半のUIは、暗黙のロールだけで実現できます。ほとんどの場合は、使用する要素を変更したり、マークアップやスタイリングを工夫することで `role` 属性を使わずに実現できるようになります。

それでも稀に、どうしても `role`属性 を使わざるを得ないケースもあります。

- WAI-ARIAにロールは定義されているが、それを暗黙のロールとして持つHTML要素が存在しない場合（[Tabs Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/)など、HTML要素が存在しないロールで表現したいUIを作る）
- HTMLの仕様では、作ろうとしているロールの構造を表現できない場合（HTMLの仕様で要素の親子関係が制限される場所に、スタイリングの都合で他の要素を入れたい場合などに、`role`属性を指定した `<div>`要素などで同等のアクセシビリティツリーを再現する）
- 限られた工数で既存の実装のアクセシビリティを改善する必要のある場合（HTML要素をなるべく変えず、アクセシビリティツリーだけを改善する）

これらの場合には `role` 属性を使うことになりますが、やはりいずれの場合も仕様書を読み解いて理解したうえで、多様な支援技術でのテストが必須になります。