折り畳み UI のスクリーンリーダー対応

最近のウェブサイトでは、ユーザーの任意操作 (クリックやタップ) によって、機能やコンテンツを展開する/折り畳むユーザーインターフェース (UI) をよく見かけます。たとえば以下のようなものです。

これらの UI は当然アクセシビリティが担保されるべきで、キーボードによる操作 (Tab キーでフォーカスを当てて Enter キーで展開/折り畳みを実行する) が可能だったり、スクリーンリーダー (音声読み上げ) でも利用可能であることが求められます。

特にスクリーンリーダーでの利用に向けては、一連のインタラクションを完遂するうえで手掛かりとなる情報がすべて音声によって伝達される必要があること、また余計な情報が音声で読み上げられないようにする必要があることを、実装上意識しなければなりません。具体的には「WAI-ARIA」という W3C 勧告仕様に基づいた実装をするわけですが、実際にいくつかのプロジェクトで試した経験も踏まえ、以下に簡単にまとめておきたいと思います。

切り替え操作子へのラベル付け : aria-label

展開/折り畳みを切り替える操作子 (<button> 要素) がアイコンのみ (テキストによるラベルを持たない) の場合、アイコン要素に対して aria-label 属性を記述します。たとえば、ハンバーガーアイコンの要素内に aria-label="メインメニュー" と記述したり、虫眼鏡アイコンの要素内に aria-label="サイト内検索" と記述したり、といった具合です。

こうすることで、切り替え操作子にフォーカスが当たったときに、その操作子の名前 (aria-label の属性値) が音声で読み上げられることが期待できます。

状態の通知 : aria-expanded

展開/折り畳みを切り替える操作子 (<button> 要素) に対して、aria-expanded 属性を記述します。機能やコンテンツが展開表示された状態のときには aria-expanded="true"、折り畳まれた状態のときには aria-expanded="false" となるように、JavaScript で属性値を動的に代入するようにします。

こうすることで、機能やコンテンツが展開される/折り畳まれるたびに、その状況がスクリーンリーダーを介して音声で通知されることが期待できます。

実際に主だったスクリーンリーダーで試したところ、以下のとおり、リアルタイムで展開/折り畳みの状態が読み上げられます。macOS VoiceOver の「じあいだひろく (字間広く)」や iOS VoiceOver の「拡大」のように、日本語として違和感のある読み上げが一部あるものの、挙動としては概ね問題なさそうです。

Windows NVDA + Chrome / Firefox / Edge
  • 折り畳み時 : 「折り畳み。」
  • 展開時 : 「展開。」
Windows Narrator + Edge
  • 折り畳み時 : 「畳まれています。」
  • 展開時 : 「展開されています。」
macOS VoiceOver + Safari / Chrome
  • 折り畳み時 : 「下位項目が折り畳まれました。」
  • 展開時 : 「じあいだひろく (字間広く)。」
iOS VoiceOver + Safari / Chrome
  • 折り畳み時 : 「折り畳まれました。」
  • 展開時 : 「拡大。」
Android TalkBack + Chrome
  • 折り畳み時 : 「折り畳まれています。」
  • 展開時 : 「展開されています。」

切り替え操作子と展開要素の紐付け : aria-controls

展開/折り畳みを切り替える操作子 (<button> 要素) に対して、aria-controls 属性を記述します。aria-controls の属性値は、展開される要素 (機能やコンテンツ) の id 属性値と同じにします。

こうすることで、切り替え操作子と、実際に展開表示される機能やコンテンツが、セマンティックに紐付けられた形になります。

高機能スクリーンリーダー JAWS には、切り替え操作子から、aria-controls で紐付けられた要素 (展開表示された機能やコンテンツ) にフォーカスをジャンプ移動できるキーコマンドが用意されているそうです。手元に検証環境が無いため未確認ですが、このような操作が多くのスクリーンリーダでも可能になれば、より便利だろうなと思います。

折り畳まれた (隠された) 要素の無視

機能やコンテンツを折り畳む (隠す) 際は、その HTML 要素に対して、CSS の display:none; が適用される実装になるかと思います。これによって当該要素は視覚的に非表示状態になり、同時にスクリーンリーダーでもアクセスできなくなります。時折、折りたたまれた (隠された) 要素に対して aria-hidden="true" を適用する必要があるか? という質問を受けることがあるのですが、display:none; が適用された時点で当該要素はアクセシビリティツリーから消える形になるので、aria-hidden 属性をわざわざ記述する必要はありません。


以上、WAI-ARIA の使用例として、参考になれば幸いです。