スマートフォンサイトの開閉するメニューとアクセシビリティ

公開

今週はスマートフォンサイトの実装を行いました。その中で、スマートフォンサイトではよく見られる、ボタンを押すとメニューが開閉する仕組みの実装がありました。実装後にiOSのVoiceOverを利用して動作を確かめたのですが、他のサイトを見ると上手く開閉することが出来ないメニューボタンがいくつか見つかりました。どのような問題が見られたか等をまとめてみたいと思います。

上手く開閉できないボタンの例

いずれもVoiceOverをオンにして操作した場合の問題です。VoiceOverがオフの場合は、問題なく操作できました。

なお、会社名・サイト名を上げていますが、上手く動作しなかったことを伝えたいだけで、他意はありませんので念のため。

1. JavaScriptの不具合?

※追記(2014年12月15日):再度確認したところ、問題なく動作するようでした。

味の素様のウェブサイトにあるメニューの開閉ボタンですが、ダブルタップしてメニューを開いても、なぜかすぐにメニューが閉じてしまいます。JavaScriptがminifyしてあるのでなかなか読めず断言は出来ませんが、JavaScriptに何らかの原因があるものと推測しています。

2. テキストコンテンツのないCSSスプライト・妥当でないマークアップ

画面上のテキストやボタンをタップすると、その要素にフォーカスした状態になってコンテンツが読み上げられるのですが、サイバーエージェント様のウェブサイトでは何度試してもフォーカスできませんでした。

マークアップを確認すると次のようになっており、CSSスプライトが利用されていました。span要素でマークアップされ、なおかつテキストコンテンツがないことで、フォーカスできないものと考えられます。

<ul>
	<li style="list-style-type:none;"><span class="icon_gnav header_btns closed" id="global_nav_btn" data-target="#sp_global_nav"></span></li>
	<li style="list-style-type:none;"><span class="icon_search header_btns closed" id="global_search_btn" data-target="#sp_global_search"></span></li>
</ul>

span要素をa要素などに変えると、フォーカスするようにはなります(但し、「リンク」や「ボタン」としか読み上げられず、ダブルタップするとどうなるのか理解できません)。

3. 画像置換

前項と似ているのですが、リクルート様のSUUMOでもフォーカスできませんでした。

マークアップは次のようになっており、CSSで画像置換に関する設定が行われていました。

<p class="dtc"><a class="icnMypage" href="javascript:void(0);" onclick="sendEventForBeacon([['eventName', 'my']]);">マイページ</a></p>

原因を探ったところ、text-indent: -9999px;の設定によりテキストが読み上げ不能になっていることが分かりました。ちなみに、WindowsのNVDAだと問題なく読み上げられました。

解決策

VoiceOverがオンの場合、意図した挙動にならないことがあるようなので、VoiceOverをオンにして確認することが必要と考えました。

また、スマートフォンサイトではパフォーマンス向上を期待しCSSスプライトの利用を検討することが多いと思われますが、メニューを示す画像であればimg要素を利用して適切にマークアップすべきと考えました。

マークアップ例

先の解決策と、以下のサイトなどをふまえて検討を行いました。

開閉ボタンをa要素でマークアップする例もありますが、どこかに遷移するものではないこと、またhref="#"とあまり意味のない記述をしなければならないことを考えると、button要素が適切と考えました(a要素の場合、「リンク メニューを開く」といった具合に読み上げられ違和感があります)。

※追記(2014年3月8日):Twitterで木達さんからコメントを頂き、Internet Explorerはimg要素に対応してください - Unreviewedを再度読みました(以前読んだのですが忘れていました...すみません)。例えば、IE11とNarratorの組み合わせだと、button要素内のimg要素のaltが読み上げられないそうです。悩ましい...。<a role="button"とすると、「ボタン」と読み上げられます。

また、WAI-ARIAaria-expandを利用してメニューが開いているか閉じているかを示したり、aria-controlsでbutton要素がどの要素を制御しているかを示すと良さそうです。

<ul>
<li><button id="menu_ctrl" aria-controls="menu"><img src="/path/to/icon_menu.png" alt="メニュー"></button></li>
</ul>

<div id="menu" aria-expanded="false">
<ul>
<li><a href="/path/to/contents1/">コンテンツ1</a></li>
<li><a href="/path/to/contents2/">コンテンツ2</a></li>
<li><a href="/path/to/contents3/">コンテンツ3</a></li>
<li><a href="/path/to/contents4/">コンテンツ4</a></li>
<li><a href="/path/to/contents5/">コンテンツ5</a></li>
</ul>
</div>

メニューはJavaScriptがオンでないと動作しないことから、JavaScriptを利用して挿入するのがベターでしょうか。その際、開閉ボタン部分はサイトマップへのリンク等をマークアップしておくのも一つの手かと思われます(例:キヤノン様ウェブサイト)。

※追記(2014年12月15日):キヤノン様のサイトは時々メニューに手を加えられており、最近では下層のEOSのページ等に行くと見られます。