はじめに
Splideは「アクセシビリティに配慮した軽量・高機能スライダー」と謳っています。
使ってみると、その謳い文句に劣らず、確かにアクセシビリティに非常に気をつかわれていることが分かります。
このSplideの公式ドキュメントにはアクセシビリティに関するページが単独で存在し、(当たり前ですが)そもそもWebアクセシビリティに明るくないと半分も理解できません。少なくとも私は完全に理解した状態でした。
そこで、W3Cのドキュメント等も踏まえカルーセルのアクセシビリティについて理解を深めつつ、Splideについても噛み砕いていきたいと思います。(かなり時間がかかった)
カルーセルのW3Cデザインパターンを確認
バージョン4から、W3CのCarousel Design Patternに準拠した上で、スクリーンリーダーが動的にコンテンツを読み上げられるようライブリージョンも導入しました。
まずは、Splideが準拠しているという、W3Cのカルーセルのデザインパターンを確認していきます。
今後の話は、これを前提に進められていきますので、ここが理解できないことには何も始まりません。
WAI-ARIAについても記載がありますが、こちらのセクションにはまとめず、Splideの説明に組み込みながら見ていきます。
“十分な”カルーセル制御に必要なもの
カルーセルに必要な機能は以下の通りであると示されています。
- 前と次のスライドを表示するためのボタン
- オプションとして、表示する特定のスライドを選択するためのコントロール、またはコントロールのグループ
- カルーセルを自動スクロールさせる場合
- 回転を停止・再開するためのボタンがある
- キーボードのフォーカスがカルーセルに入ると回転が停止する
- マウスがカルーセルの上に乗っている間は回転を停止する
キーボードインタラクション
自動スクロールさせる場合
カルーセル内の要素にキーボードのフォーカスが当たった時は、スライドの自動スクロールは停止させます。
ユーザが自動スクロールの再生・停止ボタンを押さない限り、回転は再開されません。
TabキーとShift + Tab
通常のタブ順序によって指定されたカルーセルのインタラクティブ要素にフォーカスを移動します。
Tabキーのためのスクリプトは必要ありません。
ボタン要素
ボタン要素は、ボタンパターンで定義されたキーボードインタラクションを実装します。
自動スクロールの開始・停止、スライドを次・前へ動かすボタンは、何度でも繰り返し押せるようにします。
自動スクロールの開始・停止コントロール
自動スクロールコントロールは、カルーセル内のタブ順序中で最初の要素にします。
回転するコンテンツの前に置くことが重要です。
ページネーションをタブ要素で使う場合
ここで言うページネーションは、カルーセルの下についてるドットなどで表示される、任意のスライドに移動できるコントロールのことです。
これをタブ要素で使う場合は、Tabsパターンで定義されたキーボードインタラクションを実装します。
3つのカルーセルタイプ
タイプ | 概要 |
---|---|
基本(Basic) | 回転、前へ次へのボタンを持つが、ページネーションを持たない |
タブ(Tabbed) | 基本的なコントロールと、タブパターンを使用して実装されたページネーションのための単一のタブストップを持つ |
グループ(Grouped) | 基本的なコントロールと、ページネーションのグループ内にタブストップを持つ ※ページネーションの各ボタンはページのタブ順序に追加されるため、キーボードユーザーにとって最も不親切 |
Splideのアクセシビリティ
さて、ここからはW3Cのデザインパターンを踏まえてSplideのアクセシビリティについて見ていきます。
カルーセルのタイプ
Splideでは、ページネーションの有無によって、基本(Basic)かタブ(Tabbed)として実装されています。
タイプ | 概要 |
---|---|
基本(Basic) | ページネーションを持たない |
タブ(Tabbed) | ページネーションを持つ。ページネーション自体はタブパターンに準拠 |
グループ(Grouped) | 該当なし |
タブ型は、カルーセルをタブUIと見なすため、それぞれのスライドをtabpanel
、ページネーションをtab
として実装する必要があります。
ランドマーク化
カルーセルにはメインコンテンツと関連性の高いものが含まれることが多く、バナーや、写真のギャラリーなど、基本的にはその中だけで情報が完結します。
Splideではカルーセルをランドマークにすることにより、支援技術に対してそれがメインコンテンツの一部であることを伝えます。
ランドマークとは
ページセクションにランドマークとしてラベル付けすることで、人間にはレイアウトなどによって伝わる構造情報を、マークアップ上で表現することができるものです。
このランドマークによって、スクリーンリーダーでセクションへの移動が可能になります。
HTML要素のmain
、header
、footer
、nav
、aside
、section
がデフォルトでランドマークロールをもっています。
regionランドマーク
ランドマークにはいくつかのロールが存在し、そのうちの1つがregionです。
regionランドマークは、ユーザがそのセクションに移動できるようにするために必要なセクションを示します。
特徴として以下があります。
- regionランドマークはラベルを持たなければならない
- 複数のregionランドマークを含む場合は、それぞれ固有のラベルが必要
- 名前付きランドマークでは適切に表現できないコンテンツを識別するために使用できる
section
要素は、アクセシブルな名前(aria-labelledby
、aria-label
、title
など)を持つ場合、regionランドマークとして機能します。
そのため、Splideではこの仕組みに準拠し、基本的にsection
でカルーセルをマークアップするように推奨していますが、div
を用いた場合も、role="region"
が自動的挿入されるため、いずれにせよルート要素はregionランドマークとなるようです。
ランドマークとは見なせないカルーセルの場合
メインコンテンツとは関連性のないものが含まれていたり、単に装飾目的のカルーセルである場合は、ランドマーク化はふさわしくありません。
その場合は、基本的な使い方ページにも記載がある通り、代わりにgroupロールを使用します。
<div class="splide" role="group" aria-label="Splideの基本的なHTML">
<div class="splide__track">
<ul class="splide__list">
<li class="splide__slide">Slide 01</li>
<li class="splide__slide">Slide 02</li>
<li class="splide__slide">Slide 03</li>
</ul>
</div>
</div>
HTMLではなく、JavaScriptのオプションからでも変更できます。
new Splide('.splide', { role: 'group' });
キーボード操作
バージョン4では、矢印キーでスライダーを移動するなどの、独自のキーボード操作はデフォルトで無効になりました。
その代わりに、W3Cで定義されれているタブのデザインパターンに必要なショートカットが有効になっています。
W3Cによれば、タブリストに必要とされるキーボードインタラクションは以下の通りです。
キー | 動き |
---|---|
Tab | タブリストにフォーカスが移動すると、アクティブなタブ要素にフォーカスを置く。 タブリストにフォーカスされている場合、タブパネルにフォーカスを移す。 |
← 左矢印 |
フォーカスを前のタブに移動する。 最初のタブにフォーカスがある場合、最後のタブにフォーカスを移動する。 |
→ 右矢印 |
次のタブにフォーカスを移動する。 最後のタブ要素にフォーカスがある場合、最初のタブにフォーカスを移動する。 |
Home(オプション) | 最初のタブにフォーカスを移動する。 |
End(オプション) | 最後のタブにフォーカスを移動する。 |
Space または Enter | フォーカスが当たったタブが自動的にアクティブにならなかった場合、そのタブをアクティブにする。 |
タブリストが垂直方向に配置されている場合、右矢印は下矢印に、左矢印は上矢印と読み替えられます。
これらはSplideでは以下のように設定されています。
キー | 説明 |
---|---|
← 左矢印 |
横並びのページネーションにおいて、フォーカスを前のボタン (RTLでは次のボタン)に移動すると同時に、対応するスライドを表示する |
→ 右矢印 |
横並びのページネーションにおいて、フォーカスを次のボタン (RTLでは前のボタン)に移動すると同時に、対応するスライドを表示する |
↑ 上矢印 |
縦並びのページネーションにおいて、フォーカスを前のボタンに移動すると同時に、対応するスライドを表示する |
↓ 下矢印 |
縦並びのページネーションにおいて、フォーカスを次のボタンに移動すると同時に、対応するスライドを表示する |
Space/Enter | 対応するスライドを表示する |
Home | フォーカスを最初のボタンに移動し、最初のスライドを表示する |
End | フォーカスを最後のボタンに移動し、最後のスライドを表示する |
keyboard
およびpaginationKeyboard
オプションによって、これらのショートカットを有効にするかどうかを変更できます。
また、ページネーションのボタンがキーによってフォーカスされると、対応するスライドは自動的に表示されますが、waitForTransition
が有効な場合は、フォーカスだけが先行することがあります。
ロービング・タブインデックス
Splideは、ページネーションのフォーカスはロービング・タブインデックスを用いられています。
ロービング・タブインデックスは、タブシーケンスに含まれてアクティブな要素はtabindex="0"
を持ち、その他すべてのフォーカス可能な要素はtabindex="-1"
を持つようにすることです。
フォーカス管理にはaria-activedescendant
というWAI-ARIAを用いることもできます。
これは、現在アクティブな子孫要素を指定するものです。
これではなくロービング・タブインデックスを用いる利点は、ユーザーエージェントが新しくフォーカスされた要素をスクロールして表示させることができることです。
Splideでこれを採用することによる利点は以下の通りと説明されています。
- ページネーションから離れた後、再度戻ってきた際、以前選択した位置から操作を再開できる
-
Tabを一度押すだけでページネーションを抜けられる
スライドが10枚ある場合、この機能がないページネーションでは10回押さないと抜けられない
自動再生の制御(WCAG 2.2.1, 2.2.2)
WCAG 2.2.1 Timing Adjustable より
コンテンツで設定される時間制限に対して、少なくとも以下のいずれかが当てはまる。
オフにする:
ユーザーはその時間制限に遭遇する前に、時間制限をオフにすることができる。
調整する:
ユーザーはその時間制限に遭遇する前に、デフォルト設定の長さの10倍以上の範囲で時間制限を調整することができる。
延長する:
ユーザーは時間制限が切れる前に警告を受け取り、少なくとも20秒間の猶予が与えられて、簡単なアクション(例えば「スペースバーを押す」)で時間制限を少なくとも10回延長することができる。
リアルタイム例外:
時間制限がリアルタイムのイベント(例:オークション)の必須部分であり、時間制限に代替手段が存在しない場合。
必須例外:
時間制限が重要であり、それを延長するとアクティビティが無効になる場合。
20時間例外:
時間制限が20時間を超える場合。
WCAG 2.2.2 Pause, Stop, Hide より
移動、点滅、スクロール、または自動更新される情報について、以下のすべて当てはまる。
移動、点滅、スクロール
以下の条件をすべて満たす場合、自動的に始まり、5秒以上続く、他のコンテンツと並行して表示されるいかなる移動、点滅、またはスクロール情報に対して、ユーザーが一時停止、停止、または非表示にするための仕組みが必要(ただし、それが不可欠なアクティビティの一部である場合を除く)。
自動更新
以下の条件をすべて満たす場合、自動的に始まり、他のコンテンツと並行して表示される自動更新される情報に対して、ユーザーが一時停止、停止、または非表示にするための仕組みが必要。または更新の頻度を制御するための仕組みが必要(ただし、それが不可欠なアクティビティの一部である場合を除く)。
Splideでは
自動再生するスライダーは以下3つの機能を持つ必要があります。
- 自動再生を再生・停止するボタンを提供する
- スライダー内の要素がフォーカスした際は、自動再生を停止する
- スライダー上にマウスがある間は、自動再生を停止する
Splideでは再生・停止ボタンを設置するには、以下のコードを貼り付けるだけで完了します。
<button class="splide__toggle" type="button">
<span class="splide__toggle__play">Play</span>
<span class="splide__toggle__pause">Pause</span>
</button>
その他はオプションでデフォルトで有効になっているため、気にしないでOK。素晴らしい。
視覚効果の低減(WCAG 2.3.3)
WCAG 2.3.3 Animation from Interactions より
アニメーションコンテンツにより、一部のユーザーが気を散らされたり、吐き気を感じることがあります。
例えば、ページをスクロールすると要素が移動する場合(スクロールに関連する本質的な移動を除く)は、前庭(内耳)の障害によって、めまい、吐き気、頭痛を引き起こす可能性があります。
ウェブページの機能や情報に不可欠なアニメーションは許可されていますが、それ以外の必要不可欠でないものは、インタラクションによって引き起こされるモーションアニメーションを無効にできるようにします。
Splideでは
CSSのメディア特性の1つに、prefers-reduced-motion
というものがあります。
これは、ユーザがページで不必要な動きを望まないかどうかを検出します。
OSで設定できる一例を示します。
- Windows 10: 設定 > 簡単操作 > ディスプレイ > アニメーションを表示する
- macOS: システム設定 > アクセシビリティ > 表示 > 動きの抑制
- iOS: 設定 > 一般 > アクセシビリティ > 視覚効果を減らす
- Android 9 以上: 設定 > ユーザー補助 > アニメーションの削除
Splideでは、prefers-reduced-motion: reduce
を検出した際、speed
とrewindSpeed
を0で上書き、autoplay
をpaused
で上書きします。
この結果、スライドのトランジションは再生されず、瞬時に表示されるようになりますが、ドラッグやスワイプ後のトランジションは必要なモーションであると判断されているため、無効になりません。
このオプションのデフォルト値は、[reducedMotion
](
これは、-1に設定した後に再びスライドが表示された際、0(あるいはその他の整数値)に戻す処理が必要になるためです。
スライダーの中でtabindexを用いてフォーカスを制御することはないと信じたいですが、仮にそのような対処が必要になった場合は、visibleおよびhiddenイベントを利用すればインデックスの切り替えを実装できます。)オプションで設定できます。
フォーカスの可視化(WCAG 2.4.7)
WCAG 2.4.7 Focus Visible より
ユーザーエージェントは、キーボードが使用されるときだけフォーカスインジケータを表示するなど、フォーカスインジケータが表示されるタイミングを最適化することができます。
また、フォーカスが見える操作モードを少なくとも一つは提供しなければなりません。
フォーカス・インジケータは時間制限があってはならず、キーボード・フォーカスが表示されているときは、そのままでなければなりません。
Splideでは
キーボードユーザに対してのみこのスタイルを有効にするには、:focus-visible
疑似クラスを利用する必要があります。
Safariは、2022/03/15にリリースされたバージョン15.4より前ではこの疑似クラスが使用できないという制約があるため、代わりに.is-focus-in
クラスが組み込まれています。
ただし、このクラスはフォーカスが外れてもすぐに取り除かれるわけではないため、:focus
擬似クラスと併用する必要があります。
/* :focus-visibleをサポートしているブラウザのためのCSS */
.splide__arrow:focus-visible {
outline: 3px solid tomato;
}
/* その他のブラウザのためのスタイル */
.splide.is-focus-in .splide_arrow:focus {
outline: 3px solid tomato;
}
フォーカス可能な要素(WCAG 1.3.1)
WCAG 1.3.1 Info and Relationships より
レンダリングされたコンテンツを通じて伝達される情報、構造、関係性は、プログラムによって解釈できるし、テキストで取得できるものにします。
Splideでは
スライダーの表示領域外のスライドに対してaria-hidden
属性を割り当て、スクリーンリーダなどの支援技術が表示されていないスライドを認識しないように設定されています。
また、スライド自体にフォーカス可能な要素が含まれている場合、その要素に対してtabindex="-1"
を適用することで、一時的にフォーカスできないようにしています。
ただし、以下の要素を含む場合は追加対応が必要です。
<area>
<audio controls>
<summary>
<video controls>
-
contenteditable
属性が有効になっている要素 -
tabindex="0"
を持った要素
どの要素に対してtabindex="-1"を適用するかは、focusableNodes
オプションで変更できます。
{
focusableNodes: 'a, button, ..., area, [contenteditable]',
}
tabindex="0"
の要素がある場合は、-1
に設定した後に再びスライドが表示された際、0
に戻すような処理が必要になります。
ARIA属性(WCAG 4.1.2)
インタラクション可能なすべての要素に、ARIA属性が設定されています。
ただし、属性値はすべて英語のため、ラベル等に割り当てられている値はページを閲覧する対象ユーザに合わせて、i18n
オプションを利用してローカライズしてあげます。
終わりに
W3Cのページも踏まえつつ、Splideのアクセシビリティページに記載されているものについて、できるだけ噛み砕いてみました。
そもそもSplideの本家ページが結構分かりやすく書かれているので、それを読めば事足りる人も多いかと思いますが、自分の理解度を高めるためにも調べ直してみました。
理解の一助となれば幸いです。