①ボタンとメニューの関係性を設定
「このボタンを押したら、このメニューが開く/閉じる」というような、ある要素から別の要素の表示を制御する関係性を表現するのがaria-controls属性である。制御される側にid属性で固有名を付けておき、制御する方にaria-controls属性でそのid属性を指定するようにする。
<button type="button" class="hamburger" aria-controls="gnav">
<span class="hamburger__line"></span>
<span class="hamburger__txt">Menu</span>
</button>
<nav id="gnav" class="gnav">
<ul class="gnav__list">~省略~</ul>
</nav>
②開閉状態を設定
現在のハンバーガーメニューの開閉状態をステートで設定する。
ボタン側には aria-expanded(制御先の要素が展開されているかどうか)。
メニュー側には aria-hidden(自分自身が非表示であるかどうか)。
を設定するようにする。メニューが開いている状態/閉じている状態を表現する場合の値は以下の通り。
- aria-expanded(ボタン側):メニューが閉じている時「false」/メニューが開いている時「true」
- aria-hidden(メニュー側):メニューが閉じている時「true」/メニューが開いている時「false」
<button type="button" class="hamburger" aria-controls="gnav" aria-expanded="false">
<span class="hamburger__line"></span>
<span class="hamburger__txt">Menu</span>
</button>
<nav id="gnav" class="gnav" aria-hidden="true">
<ul class="gnav__list">~省略~</ul>
</nav>
③CSSとJSにステートを反映
aria-expandedとaria-hiddenはいずれもステート(状態)であり、ユーザの操作によってリアルタイムにその状態は変化する。したがって、HTMLに記述した初期状態から変化があった場合には当然aria-属性の値も動的に変更する必要がある。 なおaria-属性はCSSからもJSからもセレクタとして利用可能なので、WAI-ARIAを使っているのであれば状態変化に関する制御についてはaria-*属性を直接セレクタとして利用するのが合理的である。
/* OPEN時スタイル */
.hamburger[aria-expanded="true"] .hamburger__line { background: transparent; }
.hamburger[aria-expanded="true"] .hamburger__line::before { top: 0; transform: rotate(45deg); }
.hamburger[aria-expanded="true"] .hamburger__line::after { bottom: 0; transform: rotate(-45deg); }
<script>
$(function(){
$('.hamburger').on('click',function(){
const expanded = $(this).attr('aria-expanded'); //開閉状態を格納
const $btnTxt = $('.hamburger__txt');
const $gnav = $('#gnav');
if(expanded === 'false'){ //メニュー非展開だったら
$(this).attr('aria-expanded',true);
$btnTxt.text('Close');
$gnav.attr('aria-hidden',false).slideDown();
}else { //メニュー展開済みだったら
$(this).attr('aria-expanded',false);
$btnTxt.text('Menu');
$gnav.attr('aria-hidden',true).slideUp()
}
});
});
</script>