【3.スクリーンリーダーでの読み上げ改善編】ここから始めようWebアクセシビリティ

## 関連記事
1. [【0.気持ち整理編】](https://qiita.com/shamokit/items/2d490f281a3bd168fdd6)
1. [【1.導入編】](https://qiita.com/shamokit/items/e8c4c2f13cc604f4fb2c)
1. [【2.キーボード操作】](https://qiita.com/shamokit/items/7a4c32979afdab74dcee)
1. [【2-1.キーボード操作改善＋スクリーンリーダー編】](https://qiita.com/shamokit/items/5ad0f0769ef3109936f5)
1. いまここ 【3.スクリーンリーダーでの読み上げ改善編】ここから始めようWebアクセシビリティ

## 振り返りと概要
前回の記事ではキーボードでコンテンツを操作できるようにしました。
記事の後半では、スクリーンリーダーの読み上げを聞いてサイト内のコンテンツがどうなっているのか耳で聞いて確かめた結果、まだ対応が不十分であることがわかりました。

この記事では読み上げ時に必要な情報を得られるようにマークアップを改善していきます。
[キーボード操作できるようにしたページ](https://shamokit.com/examples/a11y/good)はこちらです。

[今回の記事の内容で修正したページ](https://shamokit.com/examples/a11y/more-good)はこちらです。

## リンク
「こちら」と読み上げられても何のことかわかりませんでした。

この修正は簡単です。
リンクの範囲を「TOPページはこちら」まで広げましょう。

リンクのテキストだけから「どこにリンクするのか」の情報を得られればGoodです。

## ボタン
「+1　ボタン」ではよくわからないので、「カウントを1増やす　ボタン」と読み上げられるようにしましょう。

この例ではやむを得ない事情でボタンのテキストを「+1から変更できない場合」を想定し、
`button`タグに`aria-label="カウントを1増やす"`を追加します。

<details>
  <summary>aria-labelの使用について</summary>

:::note warn
`aria-label`は極力使用しない方がいいです。

+1というテキストが表示されただけのボタンより、ボタンテキストに「カウントを1増やす」というテキストが書かれたボタンのほうがより多くのユーザーにそのボタンで何を操作できるのかを伝えることができます。

同様に、アイコンだけのボタンも人によってそれが何かわからなかったり違う意味にとらえたりしてしまう可能性があるため、できるだけテキストを添えた方が良いでしょう。

また、ボタンを説明するテキストがすでに存在する場合は`aria-labelledby`を使用しましょう。
例えば

```html
<h2 id="description">カウントを1増やす</h2>
<button type="button" aria-labelledby="description">+1</button>
```

このような感じです。
:::

</details>

これで少し改善されましたが、いまカウントがいくつなのかも読み上げられると嬉しいですよね。

ということで、「クリックするとメッセージが表示されます！」「n回クリックしました！」の部分に`role="status"`を追加しましょう。
この状態でボタンをクリックするとこの`role="status"`が付いた要素のテキストが変更されるたびに変更されたテキストが読み上げられます。

これでボタンの修正は終わりです。

## アコーディオン(buttonでの実装)
アコーディオンはいくつか説明があるのでまずは対応後のコードを貼ります。

```html
<button
	id="accordion"
	type="button"
	aria-expanded={accordionOpen}
	aria-controls="accordion-content"
>
	buttonでの実装
</button>
<div
	id="accordion-content"
	hidden={!accordionOpen}
	aria-labelledby="accordion"
>
	このページ内のコンテンツは、キーボードで操作できます！
</div>
```

1. ボタンと開閉するコンテンツにidを振る
2. ボタンに`aria-controls="開閉するコンテンツにつけたid"`をつける
3. 開閉するコンテンツに`aria-labelledby="ボタンのid"`をつける
4. ボタンに`aria-expanded="開いていればtrue、閉じていればfalse"`をつける
これが読み上げを改善してくれます。
5. 開閉するコンテンツに`hidden="開いていればfalse、閉じていればtrue"`をつける
これがないとアコーディオンが閉じている時もその中身が読み上げられてしまいます。

をします。
UIライブラリやフレームワークを使っている場合は割と簡単ですが、jQueryや素のJSで書く場合は属性値の変更があるので少し面倒ですね。

ここまで対応するとボタンをクリックした時に開閉状態が読み上げられるようになります。

## タブ
こちらも先にコードを貼ります。

```html
<div role="tablist" aria-label="動物">
	<button
		role="tab"
		aria-controls="tab-1"
		aria-selected={activeTab === 1}
		id="tab-1"
		tabindex="0"
	>
		哺乳類
	</button>
	<button
		role="tab"
		aria-controls="tab-2"
		aria-selected={activeTab === 2}
		id="tab-2"
		tabindex="-1"
	>
		魚類
	</button>
	<button
		role="tab"
		aria-controls="tab-3"
		aria-selected={activeTab === 3}
		id="tab-3"
		tabindex="-1"
	>
		鳥類
	</button>
</div>
<div role="tabpanel" aria-labelledby="tab-1" id="tabpanel-1" class="tabpanel" tabindex="0" hidden={activeTab === 1 ? false : true}> // activeならtrue、それ以外はfalse
	猿、ゴリラ、一般人
</div>
<div role="tabpanel" aria-labelledby="tab-2" id="tabpanel-2" class="tabpanel" tabindex="0" hidden={activeTab === 2 ? false : true}>
	たい焼き
</div>
<div role="tabpanel" aria-labelledby="tab-3" id="tabpanel-3" class="tabpanel" tabindex="0" hidden={activeTab === 3 ? false : true}>
	ペンギン
</div>
```

1. タブボタンとタブパネルにidを振る
2. タブボタンを囲うタグに`role="tablist"`をつける
これをつけるとその中のタブの個数がタブの読み上げ時含められます。
3. タブボタンを囲うタグに`aria-label="タブの説明"`をつける
ここは任意です。タブに差し掛かった時に何のタブかわかるのであれば不要です。
つけるとタブに差し掛かった時にその名前が読み上げられます。
4. タブボタンに`role="tab"`をつける
フォーカス時タブと読まれます。
5. タブボタンに`aria-controls="タブパネルのid"`をつける
6. タブパネルに`role="tabpanel"`をつける
フォーカス時タブパネルと読まれます。
7. タブパネルに`aria-labelledby="タブのid"`をつける
これをつけるとタブパネルにフォーカスした時に該当のタグのテキストが読み上げられます。
8. 選択中のタブに`aria-selected="true"`それ以外に`aria-selected="false"`をつける

をします。

ここまで対応するとアクティブなタブボタンにフォーカスされた時に「フォーカスしたタブボタンのテキスト」、「タブの中に何個のタブボタンが含まれているか」、「タブリストにつけたaria-labelの値」が読み上げられるようになります。

また、左右キーでタブボタンを選択した時「タブボタンのテキスト」、「何個目のタブボタンか」が読み上げられ、
タブパネルにフォーカスした時はそのタブボタンのテキストが読み上げられます。

:::note info
3番目の「タブボタンを囲うタグに`aria-label="タブの説明"`をつける」については、`aria-labelledby`で別のテキストに指定されているidを指定した方がいいように思いますが、VoiceOverはこれに対応していないようでした。

`aria-label`は翻訳されないとの情報もありますが、VoiceOverで確認したところ翻訳されているようです。
一旦`aria-label`での指定が今の所いいのかなと思います。
:::

## ここまで
ここまでの対応で、読み上げでページ上のコンテンツを読んでいる人に対しても適切な対応をすることができました。

見てきてわかったように、対応内容が多そうに見えて実は既存の実装からタグを変更したり`role`や`aria-`属性をつけるようなものがほとんどで、知識は必要だけどあらかじめ対応が必要なことがわかっていれば誰でも最低限の実装はできることがわかったかと思います。

まずはよくあるタブやモーダル、アコーディオンなどのコンポーネントについてアクセシビリティの単語と一緒に検索してみることから始めて、より多くの人が情報を得られるように少しずつ改善をしていきましょう！

次回の記事が最後になります。（多分）
次回はMacのVoiceOverでランドマークを表示し、いくつか改善をしてみましょう。
（Windowsユーザーの方はすみません）

## `aria-label`と`aria-labelledby`、`<title>`、スクリーンリーダー用の隠しテキストについて
個人的には以下で考えています。

- 大前提として基本的にテキストを画面上に表示した方がいい（`aria-label`も`<title>`も使用しない）
    - でもそうできない場合（やそうしないほうが視覚的に得られる情報が減ってむしろいい場合）も多い
- 時点で`aria-labelledby`（これについてはそもそもテキストを置けない事情がある文脈でデザインされていることが多い「はず」なので選択肢に入れられないことが多い　デザイナにまず確認は取ったほうがいいです）
- `button`のなかに
    - `img`タグがある場合
        - `alt`を正しく指定する
    - `svg`タグがある場合
        - `svg`タグ内に`title`タグを配置するとツールチップが出る。荒れない画像としておきたい場合が多いと思うので`aria-label`と`role="img"`をつけることのほうが多い
        - 検索エンジンへの効果を考えるとimgにalt指定が一番良さそう　昔はIEなどでバグがあった覚えがあるけど今はどうだろうか…
        - 時点で隠しテキスト（tailwindでいうsr-only）

アクセシビリティをよくすることだけにこだわりすぎて、元々サービスやサイトを見ている人にとって逆に使いにくくなってしまったら元も子もありません。
各サイトやサービスでデメリットとメリットを理解していい感じのバランスでやっていくのがいいのかなぁと思います。（それが難しいですが）
まずは見た目が変わらない範囲、作業量が少ない範囲から「なんかちょっと便利になったよね」になるのをこのシリーズの記事では目指しています。