前回はナビゲーションに開閉用のbutton要素を追加し、aria-labelledby属性を使用してsvg要素をメニューアイコンだと明示させるところまでを実装しました。
今回はbutton要素の操作に応じて、ナビゲーションの開閉までを実装します。
<nav class="global-nav">
<button class="global-nav__button" type="button">
<span class="global-nav__button-icon">
<svg role="img" aria-labelledby="title">
<g>
<title id="title">メニューアイコン</title>
<desc>3本の横線が縦に並び、メニューの折りたたみを表している</desc>
<path ...>
</g>
</svg>
</span>
<span class="_visually-hidden">メニュー</span>
</button>
<ul class="global-nav__list">
<li class="global-nav__item"><a href="/about/">About</a></li>
<li class="global-nav__item"><a href="/service/">Service</a></li>
<li class="global-nav__item"><a href="/project/">Project</a></li>
<li class="global-nav__item"><a href="/job/">Recruit</a></li>
<li class="global-nav__item"><a href="/blog/">Blog</a></li>
<li class="global-nav__item"><a href="/contact/">Contact</a></li>
</ul>
</nav>
前回までのコードは上記になります。
開閉を制御するbutton要素、開閉によって表示が切り替わるul要素、全体を囲むnav要素の3つに注目していきましょう。
現在この記事をどんな環境で閲覧しているでしょうか。MD-Blogのナビゲーションは、表示領域が狭い環境では項目がかさばってしまうため、右上に赤丸のボタンを表示し、タップやクリック操作でメニューが展開されるように実装されています。
ナビゲーションの状態は見ればすぐに分かりますが、キーボードユーザーには伝わりません。
この展開されている・折りたたまれているを伝えるためにaria-expanded属性を使用します。
aria-expanded属性は、要素のグループ、または要素が制御する別の要素が現在展開されているか、折りたたまれているかを示すものです。
値はtrue/falseで、trueの場合は展開されている、falseの場合は折りたたまれている状態を明示します。
現在は表示領域が狭いスマートフォンで閲覧しているということにします。
<nav class="global-nav" aria-expanded="false">
<button class="global-nav__button" type="button">
<span class="global-nav__button-icon">
<svg role="img" aria-labelledby="title">
<g>
<title id="title">メニューアイコン</title>
<desc>3本の横線が縦に並び、メニューの折りたたみを表している</desc>
<path ...>
</g>
</svg>
</span>
<span class="_visually-hidden">メニュー</span>
</button>
<ul class="global-nav__list">
<li class="global-nav__item"><a href="/about/">About</a></li>
<li class="global-nav__item"><a href="/service/">Service</a></li>
<li class="global-nav__item"><a href="/project/">Project</a></li>
<li class="global-nav__item"><a href="/job/">Recruit</a></li>
<li class="global-nav__item"><a href="/blog/">Blog</a></li>
<li class="global-nav__item"><a href="/contact/">Contact</a></li>
</ul>
</nav>
少し難しいところなのですが、aria-expanded属性は開閉によって表示・非表示になる要素の親要素、または開閉を制御する要素に付与します。
展開された時に表示されるであろうul要素に付与してしまいそうになりますが、表示の状態ではなく開閉の状態を示すものなので、親要素であるnav要素に付与しています。
aria-expanded="false" なので、現在はナビゲーションは折りたたまれているということになります。
開閉の状態とは別に表示の状態も明示する必要があります。
button要素の操作でnav要素のaria-expandedのtrue/falseを切り替えると同時に、表示の状態を示すaria-hiddenを使用して、ul要素のメニューが表示されているかを示したいと思います。
aria-hidden属性は、前述のとおり要素の表示状態を示すものです。
値はtrue/falseで、trueの場合は非表示、falseの場合は表示を明示します。
<nav class="global-nav" aria-expanded="false">
<button class="global-nav__button" type="button">
<span class="global-nav__button-icon">
<svg role="img" aria-labelledby="title">
<g>
<title id="title">メニューアイコン</title>
<desc>3本の横線が縦に並び、メニューの折りたたみを表している</desc>
<path ...>
</g>
</svg>
</span>
<span class="_visually-hidden">メニュー</span>
</button>
<ul class="global-nav__list" aria-hidden="true">
<li class="global-nav__item"><a href="/about/">About</a></li>
<li class="global-nav__item"><a href="/service/">Service</a></li>
<li class="global-nav__item"><a href="/project/">Project</a></li>
<li class="global-nav__item"><a href="/job/">Recruit</a></li>
<li class="global-nav__item"><a href="/blog/">Blog</a></li>
<li class="global-nav__item"><a href="/contact/">Contact</a></li>
</ul>
</nav>
button要素の aria-expanded="false" と ul要素の aria-hidden="true" により現在のナビゲーションは、折りたたまれており、コンテンツが非表示であることを明示することができるようになりました。
aria-expanded="true" と aria-hidden="false" に反転させると、ナビゲーションは展開されておりコンテンツは表示されていることを明示します。
今回はCSS/JavaScriptの実装についての説明は省いていますが、CSSでは
button[aria-expanded="false"] {
// 展開時のbutton要素のスタイル
}
ul[aria-hidden="false"] {
// 展開時のul要素のスタイル
}
のように記述することができ、それに合わせてJavaScriptでもbutton要素のクリックイベントをトリガーに、aria-expandedとaria-hiddenの値を変更することで、実際に動くナビゲーションとなります。
今回は状態の変化を伴うaria属性の実装をしました。
そしてインクルーシブなナビゲーションはこれで一区切りとします。
ここで書いたコードが最適解というわけではなく、HTMLやWAI-ARIAの仕様はきっとこれからどんどん変化していくと思います。新しい技術を追うのは大変ですが、同時にもっといいものが作れるかもしれない楽しみや、誰にとってもやさしい、インクルーシブなウェブへの近道が見えてくる嬉しさがあります。
ナビゲーションに限らず、ナビゲーションもこれに限らず、誰もが使いやすいウェブサイトをこれからも模索していきたいです。