[JavaScript] aria-expanded 属性で要素を開閉する機能を実装
ナビゲーションのサブメニュー開閉用にキーボードでも操作しやすいボタンを付ける。
身体的にマウス操作の苦手な人もいる。そういう方へ情報発信するサイトなら、サブメニューの開閉に一般的なマウスオーバー以外の機能も必要。
HTML の aria-expanded 属性と CSS で要素を開閉表示する。
[JavaScript]
function ToggleAriaExpanded( el ) {
if ( 'true' !== el.getAttribute( 'aria-expanded' ) ) {
el.setAttribute( 'aria-expanded', 'true' );
} else {
el.setAttribute( 'aria-expanded', 'false' );
}
}
クリックしたボタンの aria-expanded 属性の値を切り替えるスクリプト。
[HTML]
<ul>
<li><a href="#">Parent</a>
<button class="sub-menu-toggle" aria-expanded="false" onclick="SubMenuAriaExpand(this)">
<span class="open" title="Sub menu open">+</span>
<span class="close" title="Sub menu close">-</span>
</button>
<ul class="sub-menu">
<li><a href="#">Child</a></li>
</ul>
</li>
</ul>
aria-expanded="false"
最初は閉じているので false。開くときはスクリプトで true に切り替える。
aria-expanded はボタンなどのコントローラ側の属性。開閉される側ではない。
onclick="ToggleAriaExpanded(this)"
ボタンクリックでスクリプトを実行する。
細かいことをいうと開閉される側の aria-hidden 属性や、コントロール対象を関連付ける aria-controls 属性などが存在するが、今回は操作上必須の箇所だけ対応。
[CSS]
[aria-expanded="false"] + .sub-menu {
display: none;
}
[aria-expanded="false"] > .close {
display: none;
}
[aria-expanded="true"] > .open {
display: none;
}
ボタンに隣接する .sub-menu の display プロパティを操作して開閉させる。
ボタンも「開く/閉じる」の表示を切り替える。
javascript でスタイルも変更できるが、「ボタンクリックで HTML のコードが変わる」ことと「属性に合わせて見た目が変わる」ことは分けて書いた方が管理しやすい。
CSS を別のモジュールで一元管理している場合もあるし、デザイナーとコーダーが別の場合も領域を分けたほうが作業しやすい。
ナビゲーションが複数ある場合
サブメニューが増えると開きっぱなしは不便かも。
グループ内で同時に開くサブメニューをひとつに制限する。
[JavaScript]
function SubMenuAriaExpand( el ) {
el.closest( 'nav' ).querySelectorAll( '.sub-menu-toggle' ).forEach( function( button ) {
if ( button !== el ) {
button.setAttribute( 'aria-expanded', 'false' );
}
} );
ToggleAriaExpanded( el );
}
el.closest( 'nav' )
指定の要素の親要素を探す。
要素名、クラス名(.class)、ID(#id) などグループ化に使っている名称を指定可能。
今回は el(クリックしたボタン)の親要素(nav)を探す。
querySelectorAll( '.sub-menu-toggle' )
クラス名 sub-menu-toggle の要素を検索する。
検索範囲はさっき closest で指定した nav の中。
forEach( function( button ){ ... } )
querySelectorAll と合わせて、見つかった要素を1個ずつ処理する。
今回はボタンの aria-expanded を false にすることで、一旦すべてのサブメニューを閉じている。
ToggleAriaExpanded( el );
最初に書いた切り替えスクリプトを呼び出し、クリックしたボタンのサブメニューは開く。
[HTML]
<button class="sub-menu-toggle" aria-expanded="false" onclick="SubMenuAriaExpand(this)">
onclick="SubMenuAriaExpand(this)"
ボタンのクリックアクションを追加したスクリプトに変更する。
まとめ
ボタンを1個ずつ付けるのは大変かもしれないが、今時ならスクリプトやCMS系のテンプレートでほぼ自動入力が主流だと思うのでこれで…。
参考リンク
aria-expanded - WAI-ARIA - W3C
Element: closest() メソッド - Web API | MDN
Element: querySelectorAll() メソッド - Web API | MDN
NodeList: forEach() メソッド - Web API | MDN