折り畳み UI のスクリーンリーダー対応
最近のウェブサイトでは、ユーザーの任意操作 (クリックやタップ) によって、機能やコンテンツを展開する/折り畳むユーザーインターフェース (UI) をよく見かけます。たとえば以下のようなものです。
- メガメニュー
- ハンバーガーアイコン (押すとメニューが展開表示される)
- 虫眼鏡アイコン (押すと検索窓が出現する)
- アコーディオン
これらの UI は当然アクセシビリティが担保されるべきで、キーボードによる操作 ([Tab] キーでフォーカスを当てて [Enter] キーで展開/折り畳みを実行する) が可能だったり、スクリーンリーダー (音声読み上げ) でも利用可能であることが求められます。
特にスクリーンリーダーでの利用に向けては、一連のインタラクションを完遂するうえで手掛かりとなる情報がすべて音声によって伝達される必要があること、また余計な情報が音声で読み上げられないようにする必要があることを、実装上意識しなければなりません。具体的には「WAI-ARIA」という W3C 勧告仕様に基づいた実装をするわけですが、実際にいくつかのプロジェクトで試した経験も踏まえ、以下に簡単にまとめておきたいと思います。
切り替え操作子へのラベル付け : aria-label または aria-labelledby
展開/折り畳みを切り替える操作子 (<button> 要素や <a> 要素) がアイコンのみ (テキストによるラベルを持たない) の場合、アイコン要素に対して aria-label プロパティを記述します。たとえば、ハンバーガーアイコンの要素内に「aria-label= "メインメニュー" 」と記述したり、虫眼鏡アイコンの要素内に「aria-label= "サイト内検索" 」と記述したり、といった具合です。
こうすることで、切り替え操作子にフォーカスが当たったときに、その操作子の名称 (aria-label 属性値) が音声で読み上げられることが期待できます。
切り替え操作子に隣接するラベル (テキスト) があって、実質的にそれが操作子の名称である場合は、aria-labelledby プロパティを用いてラベルと操作子を紐付ける形にしてもよいでしょう。
状況の通知 : aria-expanded
展開/折り畳みを切り替える操作子 (<button> 要素や <a> 要素) に対して、aria-expanded ステートを記述します。機能やコンテンツが展開表示された状態のときには「aria-expanded= "true" 」、折り畳まれた状態のときには「aria-expanded= "false" 」となるように、JavaScript で属性値を動的に代入するようにします。
こうすることで、機能やコンテンツが展開される/折り畳まれるたびに、その状況がスクリーンリーダーを介して音声で通知されることが期待できます。
たとえば Windows の NVDA は、機能やコンテンツが展開表示される (aria-expanded= "true") と音声で「展開」と伝えてくれます。逆に折り畳まれる (aria-expanded= "false") と「折り畳み」と伝えてくれます。IE と併用している場合は、これらの通知はリアルタイムで (切り替え操作子を押すたびに) 行なわれます。(Firefox と併用している場合は、現時点では残念ながらリアルタイムの通知はしてくれないので、改めて切り替え操作子にフォーカスを当て直して、そのときの状況を伝えてもらう必要があります。)
また OS X の VoiceOver は、機能やコンテンツが折り畳まれたとき (aria-expanded= "false") にのみ「下位項目が隠されました」と伝えてくれます。Safari と併用している場合は、この通知はリアルタイムで行なわれます。展開表示されたとき (aria-expanded= "true") の通知は特にありませんが、「隠されている情報がある場合にそれを展開するようユーザーに促すことができればよい」という割り切りなのでしょうか。
ちなみに iOS の VoiceOver は、機能やコンテンツが展開表示されている (aria-expanded= "true") と「表示されました」と伝えてくれ、逆に折り畳まれている (aria-expanded= "false") と「隠されました」と伝えてくれます。ただし現時点ではリアルタイムの通知は不安定で、改めて切り替え操作子にフォーカスを当て直して、そのときの状況を伝えてもらうのが確実という状況です。
なお、Android の TalkBack は、現時点では aria-expanded に応じた通知はしてくれないようです。
Windows IE + NVDA の組み合わせ以外は、いずれもまだ挙動が微妙な感じですが、今後のアップデートに期待したいところです。
切り替え操作子と展開要素の紐付け : aria-controls
展開/折り畳みを切り替える操作子 (<button> 要素や <a> 要素) に対して、aria-controls プロパティを記述します。aria-controls の属性値は、展開される要素 (機能やコンテンツ) の id 属性値と同じにします。
こうすることで、切り替え操作子と、実際に展開表示される機能やコンテンツが、セマンティックに紐付けられた形になります。
高機能スクリーンリーダー JAWS には、切り替え操作子から、aria-controls で紐付けられた要素 (展開表示された機能やコンテンツ) にフォーカスをジャンプ移動できるキーコマンドが用意されているそうです。手元に検証環境が無いため未確認ですが、このような操作が多くのスクリーンリーダでも可能になれば、より便利だろうなと思います。
折り畳まれた要素の無視 : aria-hidden
機能やコンテンツを折り畳む (隠す) 際は、その HTML 要素に対して、CSS の display:none; が適用される実装になっていると思います。これによって当該要素は視覚的に非表示状態になります。
多くのスクリーンリーダーは、display:none; が適用されている要素を読み上げない挙動をするので、特に大きな問題はなさそうですが、より厳密なセマンティクスという意味では、当該要素に対して aria-hidden ステートも記述しておくとよいでしょう。機能やコンテンツが展開表示された状態のときには「aria-hidden= "false" 」、折り畳まれた状態のときには「aria-hidden= "true" 」となるように、JavaScript で属性値を動的に代入するようにします。こうすることで、スクリーンリーダーが読み上げ対象とすべきか否かを、明示的にソースコードに盛り込むことができます。
以上、WAI-ARIA の応用例として、参考になれば幸いです。