slickのアクセシビリティを調べる:後編
JavaScript前回からの続き。
あらすじ
slick のアクセシビリティを見ていた。
前回は、「戻る/進む」ボタンと、各スライドの role
と aria-
を調べた。
https://codepen.io/dkrk/pen/aQXZrO
(以下で掲載するマークアップ部分の、余計な属性や class は削除ずみ)
.slick-dots
dots
は、スライダーのページャーにあたる。
<ul class="slick-dots" style="" role="tablist">
〜〜〜省略〜〜〜
<li role="presentation" class=""><button type="button" role="tab" id="slick-slide-control02" aria-controls="slick-slide02" aria-label="3 of 2" tabindex="-1">3</button></li>
色々な属性があった。
- role="tablist"
- role="presentation"
- button の role="tab"と aria-controls
- aria-label
- tabindex
aria-label
と tabindex
は前回触れたので、それ以外を調べてみる。
role="tablist"
ul
要素に tablist
がある。
<ul class="slick-dots" role="tablist">
前回、スライダー部分に出てきた tabpanel
のおさらいをすると、
tablist
があってtab
があってそのリソースがtabpanel
tab
とtabpanel
は関連付ける必要があるtabpanel
はtablist
の近くにある
ということでこれが tablist
にあたる。
ここは後述。
role="presentation"
li
要素に presentation
ロールというのが指定されている。
<li role="presentation" class="">
Accessible Rich Internet Applications (WAI-ARIA) 1.1 日本語訳
装飾とかに使ってるけど文書的には全く意味のない、そんな要素に与えるロール。
空 span
とか。
長いし難しいけどこういう説明もある。
presentationロールは、要素に対するデフォルトのアクセシビリティAPIロールが存在することを意味する、暗黙のネイティヴセマンティックスを持つ要素で使用される。追加の子孫要素が与えられる場合、一部の要素はただ単に完結する。たとえば、HTMLにおいて、(gridロールとマッチする)table要素は、順番にthまたはtdの子(gridcell、columnheader、rowheaderロール)を要求する、trの子孫(rowロール)を要求する。同様に、リストはリスト項目の子を必要とする。要素のセマンティックスを完全なものにする子孫要素は、必須の所有される要素としてWAI-ARIAに記載される。
presentationの明示的または継承されるロールをもちかつフォーカス可能でない任意の要素に対して、ユーザーエージェントは、その要素に対するロール固有のWAI-ARIAステートおよびプロパティを無視しなければならない。たとえばHTMLにおいて、presentationのロールをもつulまたはol要素は、ulまたはolが対応するlistロールがlistitemの必須の所有される要素を持つので、li要素の暗黙のネイティヴセマンティックスを取り除かさせる。同様に、HTMLのtable要素がWAI-ARIAロールに直接対応する暗黙のネイティヴセマンティックロールを持たないが、HTML仕様は要素がtable要素の必須の構造的な子孫であることを示すため、そのthead/tbody/tfoot/tr/th/td子孫の暗黙のネイティヴセマンティックスもまた削除される。
「暗黙のネイティヴセマンティックス」がうまい具合に解釈できないのでググった。
暗黙の ARIA セマンティックと強いネイティヴセマンティックについて - 血統の森+はてな
どうやら、HTML5 の nav
要素 = navigation のように、「要素自体が役割を持っていること」と解釈して良さそう。
そしてそれを削除するとあるので、役割を無視させることができるのだろう。
さらに「子要素に li
が必要」という役割そのものを消し去るため、直下にある li
もその意味を持たなくなる。
効果があるのは、テーブルレイアウト。
table
タグで作られたレイアウトと言うのは、配下の th
とか tr
とかも解釈させてしまうけど、この role
を添えることで、配下の th
だとか tr
だとかの役割を無視させ、内部のコンテンツに集中させることができる。
また、同じくレイアウト目的に使われ、文書的には全く意味のない画像である「スペーサー」にも使える。
buttonのrole="tab"とaria-controls
presentation な li
要素の中に、button
が存在している。
<button type="button" role="tab" id="slick-slide-control02" aria-controls="slick-slide02" aria-label="3 of 2" tabindex="-1">3</button>
やっと role="tab"
が出てきた。
加えて aria-controls
というのと、前回紹介した aria-label
や tabindex
が出ている。
まず tab
ロールについて。
Accessible Rich Internet Applications (WAI-ARIA) 1.1 日本語訳
- tab を持つ要素は tablist 要素に所有される(子孫である)べき
- アクティブな tab ロールの値に関連づけられる tabpanel は見えるべき
- 関連づけられる tab を選択するまで他の tabpanel を非表示にするべき
- tab の aria-selected をアクティブなら true に、非アクティブなら false にする必要がある
続いて aria-controls
を調べる。
Accessible Rich Internet Applications (WAI-ARIA) 1.1 日本語訳
aria-controls
で設定した値は、tabpanel
の id
として参照できる。
実際に aria-controls
の値が、slick-slide の tabpanel
に対応しているか調べる。
dots 部分
<ul class="slick-dots" style="" role="tablist">
〜〜〜省略〜〜〜
<li role="presentation" class=""><button type="button" role="tab" id="slick-slide-control02" aria-controls="slick-slide02" aria-label="3 of 2" tabindex="-1">3</button></li>
スライド部分
<ul class="slick-initialized slick-slider slick-dotted">
〜〜〜省略〜〜〜
<li class="slick-slide" aria-hidden="true" tabindex="-1" role="tabpanel" id="slick-slide02" aria-describedby="slick-slide-control02">3</li>
dots 部分の aria-controls
が「slick-slide02」になっている。これは 3 番目のスライド(index が 0 から始まるため)を指している。
そして、slick-slide の id も「slick-slide02」になっている。
tab と tabpanel の関係が一応成立しているのがわかった。
わかったこと
- aria-label を用いてその要素の機能を示せるけど、画面内で確認できるテキストがあるなら aria-labelledby を使用する。
- aria-hidden を true にすると、その要素が不可視であることを示すことができる。画面内で見えたタイミングで false に戻す必要がある。
- tabindex は、0 か-1 にするべき。-1 は tab キーなどでフォーカスしない。
- presentation ロールは、レイアウトのために用いられた要素などの役割を無効化する。
- tablist ロールの要素は tab を所有し、その外に tabpanel が存在する。tabpanel は tab と結びつけるべきで、アクティブな tab と見える tabpanel は同じでなくてはならない。
色々思うところがあった。
tabindex=0
が端の非表示スライドまでに及んでいるから、tab キーで不可視のスライドにフォーカスが当たっちゃうとか。
centerMode だと可視のスライドが増えるから、tab に aria-selected
を指定して「このスライドを選んでいること」を主張した方がいいんじゃないかなとか。
あと slick にする部分に ul
とか ol
とかつけるのはやめた方が良さそう。
中にラッパー要素がぐちゃぐちゃと入るので。