アクセシビリティに対応したTooltipってどんな作り？ ― 【後編】 Tooltipの読み上げ

## これはなに

https://qiita.com/gilly/items/2d3401eb6e869ae88554

この記事は、上記の記事の続きです。

W3Cの[ARIA Authoring Practices Guide (APG) | Tooltip Pattern](https://www.w3.org/WAI/ARIA/apg/) を読み解きながら、アクセシビリティに対応したTooltipの実装の読み上げについての記事です。

https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/

### Tooltipの読み上げの挙動についての詳細は書かれていない

W3Cの[ARIA Authoring Practices Guide (APG) | Tooltip Pattern](https://www.w3.org/WAI/ARIA/apg/) には読み上げの詳細は記載されていませんでした。
ただ1文、下記の通り「 `aria-describedby` でTooltipのトリガー要素は、Tooltipを参照する」とありました。

>The element that triggers the tooltip references the tooltip element with aria-describedby.

なので、ここからは [Develop example of tooltip design pattern · Issue #127 · w3c/aria-practices](https://github.com/w3c/aria-practices/issues/127) に対応したTooltipの実装のデモを提供してくれている、下記のGitHubのコードを頼りに私なりの解釈をまとめたいと思います。

https://github.com/ZoeBijl/apg-tooltip?tab=readme-ov-file

Tooltipのデモページはこちらです。

https://zoebijl.github.io/apg-tooltip/


## Tooltipで使用するWAI-ARIA

前編でも紹介しましたが、今回頻出するのでおさらいです。
これらのWAI-ARIAが読み上げに関わってきます。

WAI-ARIA | 用途
--- | ---
`role="tooltip"` | Tooltipのポップアップとして表示される要素のroleとして使用します
`aria-describedby` | Tooltipがフォーカスを受け取る要素に、Tooltipの内容を参照情報として渡します
`aria-labelledby` | Tooltipがフォーカスを受け取る要素に、Tooltipの内容をメインの読み上げ要素として渡します

どのように使うのか事例を見ていきたいと思います。
なお、今回は下記の環境での事例です。

:::note info
- ブラウザ：**Chrome**
- 読み上げの支援技術：**VoiceOver**
:::


## 補足情報を含むTooltip

先に紹介した[デモページ](https://zoebijl.github.io/apg-tooltip/)のコードを参考にしながら説明したいと思います。

Tooltipに記載した内容を補足情報として扱いたい場合、 `aria-labelledby` を使います。


### `button` タグの場合

```html
<div class="tooltip-container">
  <button type="button" aria-describedby="description">
    設定
  </button>
  <p id="description" role="tooltip" class="hidden">設定の表示と管理</p>
</div>
```

### `a` タグの場合

```html
<p>
  昼食後、私たちは
  <span class="tooltip-container">
    <a href="https://www.alpen-paesse.ch/en/alpenpaesse/sustenpass/" aria-describedby="link-description" data-tooltip-trigger>
      ズステンパス
    </a>
    <span id="link-description" role="tooltip" class="hidden">スイスの美しい山道</span>
  </span>
  で集合写真を取るため。
</p>
```

### VoiceOverでの読み上げ

タグの組み合わせ | 読み上げ | デモページのコードを読み上げた場合
--- | --- | ---
`button` タグ + `aria-describedby` | 「`button` タグのテキスト description `aria-describedby` のテキスト、ボタン」 | 「設定 description 設定の表示と管理、ボタン」
`a` タグ + `aria-describedby` | 「`a` タグのテキスト、リンク」 | 「ズステンパス、リンク」

お気づきでしょうか？
`button` タグでは補足文も読み上げに含まれましたが、 `a` タグでは読み上げられませんでした。
`a` タグでTooltipの内容を読み上げさせようと思うと、Tooltipはフォーカスを受け取らないため、地のテキストと同じで `VoiceOver key + ←→` でTooltipに入って読み上げてもらわなければいけません。

リンクをボタンのUIで提供している場合、 `aria-describedby` の読み上げはトリガー要素にフォーカスがあたったときにされないので、注意が必要そうです。

ブラウザ側が `a` タグでも補足文を読み上げてもらえるように対応してくれるといいなと頭をよぎりましたが、文中のaタグで表現するならば前後の文章を工夫して表示するようにするほうが良いと私は思いました。


```diff_html
<p>
-  昼食後、私たちは
+  昼食後、私たちはスイスの美しい山道である、  
-  <span class="tooltip-container">
-    <a href="https://www.alpen-paesse.ch/en/alpenpaesse/sustenpass/" aria-describedby="link-description" data-tooltip-trigger>
+  <a href="https://www.alpen-paesse.ch/en/alpenpaesse/sustenpass/">
-      ズステンパス
+    ズステンパス  
-    </a>
-  </a>
-    <span id="link-description" role="tooltip" class="hidden">スイスの美しい山道</span>
-  </span>
  で集合写真を取るため。
</p>
```

diffをなくすと下記の状態です。

```html
<p>
  昼食後、私たちはスイスの美しい山道である、
  <a href="https://www.alpen-paesse.ch/en/alpenpaesse/sustenpass/">
    ズステンパス
  </a>
  で集合写真を取るため。
</p>
```

## メインのラベルとしてのTooltip

アイコンボタンなどにTooltipをつけた時です。
Qiitaの記事エディタのツールバーにも、絵文字の選択などで使われています。

```html
<div class="tooltip-container" data-tooltip-position="top">
  <button type="button" aria-labelledby="tooltip">
    <span aria-hidden="true">💛</span>
  </button>
  <p id="tooltip" role="tooltip" class="hidden">いいね</p>
</div>
```

### VoiceOverでの読み上げ

タグの組み合わせ | 読み上げ | デモページのコードを読み上げた場合
--- | --- | ---
`button` タグ + `aria-labelledby` | 「`button` タグのテキスト、ボタン」 | 「いいね、ボタン」
`a` タグ + `aria-labelledby` | 「`a` タグのテキスト、リンク」 | デモにはありませんでした

`aria-labelledby` はアクセシブル名を定義します。
`button` タグも　`a` タグも同じ読み上げの挙動です。


## `role="tooltip"` の読み上げ

Tooltipのトリガーとなったタグの読み上げのあとに `VoiceOver key + ←→` で要素を移動すると、Tooltipの読み上げが次の順でされます。

1. `role="tooltip"` を適応したタグのテキスト、ツールチップ」
2. 「`role="tooltip"` を適応したタグのテキスト」
3. 「終わり、 `role="tooltip"` を適応したタグのテキスト、ツールチップ」

なぜか3回おなじテキストが読み上げられることになりました :thinking: 

ちょっとイメージし難いと思うので、メインのラベルとしてのTooltipの「いいね」のTooltipの読み上げを例にすると

1. 「いいね、ツールチップ」
1. 「いいね」
1. 「終わり、いいね、ツールチップ」

と読み上げられます。

身近な人に読み上げの支援技術を普段から利用している人がいないため私の想像になってしまいますが、これは期待している挙動ではないと思いました。


## `role="tooltip"` のタグを `aria-hidden="true"` にすべきか？

`role="tooltip"` タグを `aria-hidden="true"` を適応することは可能でした。
適応する前に、ARIAの原則に立ち返ってみましょう。

[ARIA Authoring Practices Guide (APG) | Read Me First](https://www.w3.org/WAI/ARIA/apg/patterns/) の冒頭にはこう書いてあります。

:::note warn
>No ARIA is better than Bad ARIA

悪いARIAより、ARIAはないほうが良い
:::

W3C の Using ARIA [2.1 First rule of ARIA use](https://www.w3.org/TR/aria-in-html/#rule1)にも下記の記述があります。

:::note warn
>If you can use a native HTML element [HTML51] or attribute with the semantics and behaviour you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.

必要なセマンティックな振る舞いが組み込まているネイティブのHTML要素を使用できる場合は、ARIAでアクセシブルにするのではなく、ネイティブのHTML用を使いましょう（意訳）
:::


### 改めて実装を考えてみる

この原則に乗っ取るならば、 メインのラベルとしてのTooltipで紹介したコードは、 `role="tooltip"` を使わず、読み上げ専用の非表示のテキストを使う、下記のようなコードが好ましいと言えると思います。

```html
<div class="tooltip-container">
  <button type="button">
    <span aria-hidden="true">💛</span>
    <span class="visually-hidden">いいね</span>
  </button>
  <p id="tooltip" class="hidden">いいね</p>
</div>
```

補足情報を含むTooltipで紹介した `a` タグの場合だと、前後の文章を工夫するのはもちろんですが、リンクをボタンのUIで提供している場合も対応できます。

例えば架空のSNSのアイコンが 🍳 だとして、このアイコンからリンクさせたい場合、Tooltipで「お料理SNSのアカウントを見る」という遷移を伝え、非表示の読み上げテキストで読み上げの支援技術を使っているユーザーにも伝えることができます。

```html
<div class="tooltip-container">
  <a  href='/'>
    <span aria-hidden="true">🍳</span>
    <span class="visually-hidden">お料理SNSのアカウントを見る</span>
  </a>
  <p id="tooltip" class="hidden">お料理SNSのアカウントを見る</p>
</div>
```


だから、[ARIA Authoring Practices Guide (APG) | Tooltip Pattern](https://www.w3.org/WAI/ARIA/apg/)では `aria-describedby` についてしか書いてなかったのではないかと思いいたりました。

## 【後編】Tooltipの読み上げのまとめ

- **No ARIA is better than Bad ARIA**
    - 本当に必要なARIAか一度考える
- `role="tooltip` を使うのは `button` タグ + `aria-describedby` の組み合わせが主
- 非表示の読み上げテキストと、 `role="tooltip` を持たないTooltipで読み上げ対応を実現する



## 参考

- https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/
- https://github.com/w3c/aria-practices/issues/127
- https://github.com/ZoeBijl/apg-tooltip?tab=readme-ov-file
- https://zoebijl.github.io/apg-tooltip/
- https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/
- https://www.w3.org/TR/aria-in-html/#rule1