slickのアクセシビリティを調べる:後編

前回からの続きです。

あらすじ

slickのアクセシビリティを見ていた。
前回は、「戻る/進む」ボタンと、各スライドのroleとaria-を調べた。

(以下で掲載するマークアップ部分の、余計な属性や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とかつけるのはやめた方が良さそう。
中にラッパー要素がぐちゃぐちゃと入るので。