#50 アクセシブルなアコーディオンを作る【ぴよぴよコーダーの開発日記】
まずはデモ。その前にアクセシブルとは何ぞや、と言うことですが、平たく言うと、あらゆる人がアクセスしやすいって意味で大丈夫かと思います。
違いがわかるだろうか。アクセシブルなデモはタブキーが動くんですね。
だから何だって感じかもしれませんが、WebアクセシビリティのガイドラインであるWCAG2.0で、こんなルールがあるそうです。
コンテンツのすべての機能は、個々のキーストロークに特定のタイミングを要することなく、キーボードインタフェースを通じて操作可能である。
ちなみに、WCAGとは、Web Content Accessibility Guidelinesの略。あらゆる人がUIにアクセスできると言うやさしい世界線のルール。
参考:アクセシブルなアコーディオンパネルにするために考えなければならないこと
↑の参考サイトはaタグでの事例がありましたが、今回はbuttonタグで実装しました。aタグといってもhrefで遷移する場所はないので。タブ操作であればbutton要素で大丈夫かなと。コードは下記
<dl id="acMenu">
<dt><button type="button" role="tab" aria-controls="accordion1" aria-selected="false" aria-expanded="false">Step.1 <span class="icon--toggle" title="メニューを開く">+</span></button></dt>
<dd role="tabpanel" id="accordion1" aria-hidden="true">Step.1の内容</dd>
</dl>
ちなみにアクセシブルじゃないほうのコードはこちら
<dl id="acMenu">
<dt>Step.1 <span class="icon--toggle">+</span></dt>
<dd>Step.1の内容</dd>
</dl>
上のほうのコードは下に比べて、なんかbutton要素以外にも、roleやらaria-controlsやら、いっぱい書かれている。これは何ぞや。ってことをこれから調べてみます。
role属性とaria属性とは?
・role属性:コンテンツの役割。roleって日本語で役だね。
・aria属性:コンテンツの状態や性質。ちなみにariaとは、Accessible Rich Internet Applicationsの略だそうです。アクセシブルなリッチなアプリ。
さて、role属性。このアコーディオンではトリガーとなるbuttonに、role="tab" という役割をつけている。アコーディオンだけど後続に開くコンテンツがあるからタブと同じ。
そして、後続の開くコンテンツには、role="tabpanel" という役割づけ。そのまんまの意味ですね。
次に、aria属性。ずらずらいっぱい書かれています。と言っても4つくらいなので、一つ一つ説明します。
・aria-controls属性:平たく言うと、labelタグにあるfor属性とinputタグのidのような関連付けができる属性。このソースでは、aria-controls="accordion1"とbuttonに付与して、開くコンテンツのほうに、id="accordion1"と同じ名前を付けて関連付けをしている。
・aria-selected属性:これもselectedと同じような機能。選択されてないときは値にfalseが入り、選択されてたらtrueが入る
・aria-expanded属性:要素の開閉の状態を示すためのWAI-ARIAの属性。まさにタブやアコーディオンのためにある属性ですね。expandは日本語で広がるだから、過去形でexpanded、広がった状態か。初期状態は広がってないから、aria-expanded="false"ということ。これはトリガーのbuttonのほうにつける属性。
・aria-hidden属性:これもそのまま表示されていないかという状態を表す。非表示の要素があったら、隠れてますよということで、aria-hidden="true"。
状態を示すaria属性は、jQueryで開いてる状態と閉じてる状態の書き換えをします。コードは下記。
$(function(){
$("#acMenu > dt > button").on("click", function() {
$(this).parent('dt').next().slideToggle();
if($(this).find('.icon--toggle').text() === '+'){
$(this).find('.icon--toggle').text('―');
$(this).find('.icon--toggle').attr('title', 'メニューを閉じる');
$(this).attr('aria-selected', true);
$(this).attr('aria-expanded', true);
$(this).parent('dt').next('dd').attr('aria-hidden', false);
} else {
$(this).find('.icon--toggle').text('+');
$(this).find('.icon--toggle').attr('title', 'メニューを開く');
$(this).attr('aria-selected', false);
$(this).attr('aria-expanded', false);
$(this).parent('dt').next('dd').attr('aria-hidden', true);
}
});
});
このif文の分岐なんなんって気もしますが、buttonをクリックしたときにアイコンが+の時は、アイコンを-に変更して、title属性にメニューを閉じるという補助文言を変更する。そしてそれぞれのaria属性の値をセットする。開いてる状態だから、aria-expandedはtrueで、選択されてるから、aria-selectedもtrueで、コンテンツは表示されているから、aria-hiddenはfalseである、閉じているときはその反対の処理。
参考:アクセシビリティを意識したWAI-ARIA実装について
参考:ReactとWAI-ARIAでアクセシブルなアコーディオンUIを実装してみた
ちなみに、上記のJSのソースにtitle属性で、メニューを開く、メニューを閉じる と、書き換えてますが、これも+というアイコンだけでは、何を意味するかわからないので、title属性で情報を補足しています。スクリーンリーダーもtitle属性を読みますが、文字列としてブラウザに表示させたいときは、imgタグでアイコンを作って、altで書き換えてもよいかもしれません。aria-label属性で明記するのもいいって、デモ作った後に気づきました。
参考:【アクセシビリティ】HTML/CSSで突っ込まれた点をメモメモ
参考:fontawesome ここのハンバーガーメニューはtitle属性だった
後日やる予定:aria-label属性とaria-labelledby属性を書き忘れていたので追加するかも。
この記事が気に入ったらサポートをしてみませんか?