必須バッジの重複読み上げを aria-hidden で解消する【アクセシビリティ改善事例】
「必須」バッジ付きのラベルと入力フォームは、Webサイトで頻繁に見かけるマークアップです。視覚的には何の問題もありませんが、スクリーンリーダーで読み上げるとわずかな問題が発生する場合があります。
この記事では「必須」が重複して読み上げられてしまう問題と、aria-hidden="true"を1つ加えるだけのシンプルな改善方法を紹介します。
読み上げの検証にはmacOSのVoiceOverとChrome(バージョン 150.0.7871.187)を使用しています。スクリーンリーダーやブラウザの種類・バージョンによって読み上げ結果が異なる場合があります。
よくあるフォームのマークアップ
まずは改善前のマークアップです。ラベルに「必須」バッジを含め、labelのfor属性とinputのid属性を紐づけた、一般的によく見る実装です。
<label for="your-name">お名前<span>必須</span></label><input type="text" id="your-name" required>以下が実装例です。
マウスやキーボードを使って視覚的に操作する分には、何の問題もありません。「お名前」が必須項目であることも一目でわかります。
スクリーンリーダーでの読み上げを確認する
このフォームをVoiceOverで読み上げると、次のようになります。
- ラベルフォーカス時:「お名前 必須」

- 入力欄フォーカス時:「お名前 必須、必須、テキストを編集」

入力欄にフォーカスした際に「必須」が2回読み上げられ、冗長になっていることがわかります。
視覚的に操作している限り冗長性は一切感じませんが、スクリーンリーダーのユーザーにとって「同じ情報を何度も聞かされる」ことは大きな負担になります。入力項目が多いフォームであれば、その負担はさらに積み重なっていくことでしょう。
なぜ「必須」が重複して読み上げられるのか
重複の原因は、「必須」という情報が2つの経路でスクリーンリーダーに伝わっているためです。
labelのfor属性とinputのid属性が紐づいているため、入力欄にフォーカスするとラベル内のテキスト(「お名前」と「必須」)がすべて読み上げられるinputにrequired属性が付与されているため、スクリーンリーダーが必須項目であることを「必須」とアナウンスする
つまり、ラベル内の「必須」テキストと、required属性由来の「必須」アナウンスが重複しているのです。どちらも単体では正しい実装ですが、組み合わさることで冗長な読み上げが生まれてしまいます。
解決法
解決法はいたってシンプルです。
<label for="your-name">お名前<span>必須</span></label><label for="your-name">お名前<span aria-hidden="true">必須</span></label><input type="text" id="your-name" required>「必須」テキストのspanタグにaria-hidden="true"属性をつけるだけです。
aria-hidden="true"を付与した要素は、見た目はそのままに、スクリーンリーダーなどの支援技術からは無視されるようになります。「必須」であるという情報はrequired属性が担ってくれるため、ラベル内のバッジは「視覚ユーザー向けの装飾」として支援技術から隠してしまう、という考え方です。
これにより以下のように読み上げられます。
- ラベルフォーカス時:「お名前」

- 入力欄フォーカス時:「お名前 必須、テキストを編集」

「必須」が1回だけ読み上げられるようになり、冗長さが解消されました。
「ラベルで必須が読まれない」のは問題ないのか
一見すると、ラベルフォーカス時に「必須」であることがわからなくなり、問題があるのではと思うかもしれません。
しかし、実際に入力を行うのは入力欄です。入力欄にフォーカスが移ればrequired属性によって「必須」であることが必ず読み上げられるため、入力が必要であることは一目瞭然です。
「必須」という情報が失われたわけではなく、required属性という適切な担い手に一本化された、と捉えるとわかりやすいかもしれません。
まとめ
ラベル内の「必須」バッジにaria-hidden="true"を1つ加えるだけで、スクリーンリーダーの読み上げから冗長さを取り除くことができました。
視覚的な確認だけでは決して気づけない問題ですが、スクリーンリーダーのユーザーにとって「同じ情報を何度も読む」ことは大きな負担です。とても小さなことですが、Webアクセシビリティを改善できた一例でした。
