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

アクセシビリティとは

Webページが、操作方法が制限される人、マウスなどで操作できない人など、あらゆる人物や環境に配慮しているかどうか、ということ。
英文字だとaとyの間に11文字あるから、a11yと呼ばれる。

様々な仕様が存在するけど、HTMLにWAI-ARIAというのがある。
要素にrole、aria-というような属性を指定して、要素が持つ役割や目的を支援技術が読み取れるようにする。

LP、小〜中規模サイトはともかく、大規模レベルになるとちゃんとガイドラインが設けられる。
海外では、アクセシビリティの不備が訴訟に繋がることも多い。
つまりエンジニアがアクセシビリティで消耗するのは避けられない事態となる。

roleとaria-とは

roleは、その要素がもつ「役割」を、支援技術に伝えるために必要な属性である。
例えば「role="dialog"」属性があれば、その要素はダイアログと伝えらえる。
単純なウィジェット的なロール(ウィジェットロール)から、「navigation」「banner」など場所を示すロール(ランドマークロール)まで種類が色々ある。

aria-は、その属性が持つ状態、プロパティを指定することができる。
例えば「aria-hidden」という属性で、非表示 / 表示という状態を示すことができる。

HTML5の要素は、それ自体が役割を明示しているものが存在する。
例えばnav要素はnavigationという役割があるため、roleでnaviationを指定するのは二重指定となり怒られる。
めんどくせぇぞARIA!

slickとは

https://kenwheeler.github.io/slick/
jQuery依存のスライダー&カルーセル用プラグイン。
導入が楽なので、jQueryを使用するページに取り入れられることが多い。
多くのプラグインには、アクセシビリティを考慮した属性付きの要素が生成される。
このslickもその1つ。

slickの設置

CodePenでcdn版slickを読み込み、accessibilityがtrue、falseのslickをそれぞれ設置。
arrow(進む、戻るボタン)とdots(●のナビ)を追加する。

そして生成されたDOMを見ていく。

.slick-arrowを見る

まず、「前後のスライドに移動する」ボタンにあたる、slick-arrowの部分。

slick-prevを見ていく。

<button class="slick-prev slick-arrow" aria-label="Previous" type="button" style="">Previous</button>

以下の属性が確認できた。

  • aria-label

aria-label

生成されたボタンには、このように「aria-label」属性がつけられている。
aria-labelについては、以下のように述べられている。

aria-label 属性の使用 - Accessibility | MDN
ARIA6: オブジェクトのラベルを提供するために aria-label を使用する | WCAG 2.0 達成方法集

要は目的を示していないオブジェクトに対して、ラベルを付けますよ、という要素。
そして、その要素にテキストがあるなら、代わりにaria-labelledbyという属性をつけ、そのオブジェクトとラベルを関連づける必要がある。

これ、そもそも「Previous」というテキストがあって、オブジェクトの目的をちゃんと示せている。
だからaria-labelledby属性を使って、「前後に移動するボタンの一部」であることを示した方が優しいのかも。

slick-slideを見る

スライド部分(.slick-slide)を見る。
汚いので余計な属性とclassは省いた。

<li class="slick-slide" aria-hidden="false" tabindex="0" role="tabpanel" id="slick-slide00" aria-describedby="slick-slide-control00">1</li>

以下の4つが確認できる。

  • aria-hidden
  • tabindex
  • role="tabpanel"
  • aria-describedby

aria-hidden

まず、aria-hiddenから。
trueの要素とfalseの要素がある。

Accessible Rich Internet Applications (WAI-ARIA) 1.0 日本語訳

要素が一部のユーザーアクションの後にのみ可視である場合、著者はaria-hidden属性をtrueに設定しなければならない。要素が提示される場合、著者はaria-hidden属性をfalseに設定しなければならないか、要素が表示されていることを示す、属性を削除しなければならない。

「しなければならない」だらけ。
要は見えない要素には、aria-hiddenをtrueにするなり非表示にしなければならない。
このスライドは見えている要素が3つあるので、5、1、2のスライドがfalseになる。
その先のスライドは、画面外にあって見えてないのでtrueにする。

<li class="slick-slide slick-active" aria-hidden="false" tabindex="-1">5</li>
<li class="slick-slide slick-current slick-active slick-center" aria-hidden="false" tabindex="0" role="tabpanel" id="slick-slide00" aria-describedby="slick-slide-control00">1</li>
<li class="slick-slide slick-active" aria-hidden="false" tabindex="0" role="tabpanel" id="slick-slide01" aria-describedby="slick-slide-control01">2</li>
<li class="slick-slide" aria-hidden="true" tabindex="0" role="tabpanel" id="slick-slide02" aria-describedby="slick-slide-control02">3</li>

CodePenのサンプルでは、slickをスライドして、
端のスライドが表示されるタイミングで、aria-hiddenが切り替わっているのが確認できる。

非表示にするというのは、
display:none; やvisibility: hidden; 、hidden属性がついた要素など。

tabindex

次に、「tabindex」。
アクセシビリティにも関わる、重要な属性のひとつ。

tabindex - HTML: HyperText Markup Language | MDN

キーボード(TABキーなど)で要素間を移動する時のフォーカス設定となる。
全ての.slick-slide要素を見ると、0と-1のどちらかが設定されていることがわかる。
-1の要素は、キーボードで到達できない場所となる。

tabindexの数値は、1以上の正の数を指定することもできる。
1,2,3…と、フォーカスの順番を指定させることができる。
ただ、0と-1だけを用いることが推奨されている。
正の数を指定することは、アクセシビリティ的にも推奨されていない。
順番を指定して死にかけた話が、調べるとたくさん出てくる。

CSS による配置はタブ順序には影響せず、要素の視覚的な順序のみを変更します。タブ順序は DOM 上の順序に対応します。

順番を変えるならCSSでやれ、そういうことだろう。

また、「対話型コンテンツでないものに使用することは避けてください」とある。
対話型コンテンツとは、下記の要素を指す。

<a>, <button>, <details>, <embed>, <iframe>, <keygen>, <label>, <select>, <textarea>

liは対話型コンテンツではない気がする。

role="tabpanel"

tabpanelというロールがついている。

Accessible Rich Internet Applications (WAI-ARIA) 1.1

tablistに含まれるtabに関連づけられた、リソースのあるコンテナ。著者はtabにaria-controls属性を用いてtabpanelを参照するか、tabpanelにaria-labelledby属性を用いてtabを参照するかのいずれかの方法で、tabpanelをtabに関連付けるべきである。tablistは一般的に、通常は先行する一連のtabpanelの近くに配置される。(※以下省略)

原文ではSHOULDが大文字Boldで表記されている。
要はtabpanelとtabが結びついてないといけない。
しかもそのtabは、tablistに含まれているものである。

tablist、どれだろう?と思ってul以下を見たら、buttonやdivが入ってて結構カオスだった。

<ul class="slider js-slide01 slick-initialized slick-slider slick-dotted">
  <button class="slick-prev slick-arrow" aria-label="Previous" type="button" style="">Previous</button>
  <div class="slick-list draggable" style="padding: 0px 50px;">
    <div class="slick-track" style="opacity: 1; width: 5908px; transform: translate3d(-2954px, 0px, 0px);">
      <li class="slider-item slick-slide slick-cloned" data-slick-index="-4" aria-hidden="true" tabindex="-1" style="width: 422px;">2</li>
        〜〜〜〜

aria-describedby

「slick-slide-control00」とか、スライドのindexに対応した説明付けが行われている。
中身が「1」なのに説明が「controll00」とか、混乱しそうだ。

これは、.slick-dotsの「aria-controls」と微妙に連動していることがわかった。
ということで、次は.slick-dotsを見ていく。
思ったよりも長くなったので、次回に続きます。