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

JavaScript

前回からの続き。

あらすじ

slick のアクセシビリティを見ていた。
前回は、「戻る/進む」ボタンと、各スライドの rolearia- を調べた。
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-labeltabindex は前回触れたので、それ以外を調べてみる。

role="tablist"

ul 要素に tablist がある。

<ul class="slick-dots" role="tablist">

前回、スライダー部分に出てきた tabpanel のおさらいをすると、

  • tablist があって tab があってそのリソースが tabpanel
  • tabtabpanel は関連付ける必要がある
  • tabpaneltablist の近くにある

ということでこれが 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-labeltabindex が出ている。

まず 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 で設定した値は、tabpanelid として参照できる。
実際に 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 とかつけるのはやめた方が良さそう。
中にラッパー要素がぐちゃぐちゃと入るので。