Accessibility

アクセシビリティ

はじめに

Splideは、が示す基準になるべく添うよう配慮しながら、スライダーのアクセシビリティ向上を図っています。このガイダンスは、次のような4つの基本要件を提示しています。

  • キーボードあるいは音声入力を使っているユーザが、個々のスライドを移動できること
  • スクリーンリーダを用いているユーザが、現在どのスライドが表示されており、かつどのようにすれば別のスライドに移動するかを理解できること
  • ものの動きに気がとられてしまう人のために、アニメーションを停止できる手段を提供すること
  • スライド内のコンテンツを読むのに時間がかかってしまう人のために、アニメーションを停止できる手段を提供すること。同時に、スライド内のコンテンツを読むための十分な時間を確保すること

自動再生の機能により、後半2つの問題はすでに解決されています。W3Cは再生・停止ボタンの提供を勧めていますが、配置するかどうかはご自身で決めてください。

以下、前半の2点について、Splideではどのような対応がなされているかについて説明していきます。

キーボード操作

ショートカット

ユーザは、矢印キーを用いてスライダーを操作することができます。

ショートカット説明
LTRでは前の、RTLでは次のページに移動
LTRでは次の、RTLでは前のページに移動
TTBで前のページに移動
TTBで次のページに移動

デフォルトでは、Splideはdocumentkeydownを監視しているため、仮に1ページ内に複数のスライダーが配置されている場合、すべてが同時に反応します。もしこの動作が好ましくない場合、keyboardオプションを'focused'に設定すると、アクティブ要素(フォーカスを持った要素)を内包したスライダーのみが反応するようになります。なお、このときスライダーのルート要素には自動的にtabindex="0"が追加されます。これはスライダーが、フォーカスできる要素を一つも持っていない可能性への対策です。

タブキーによる操作

ユーザはキーを用いて、現在見えているスライド、矢印ボタンおよびページネーションを移動することができます。

  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09

slideFocusオプションをfalseにすればスライドへのフォーカスを無効にできますが、この場合は最初に引用した要件の1つ目を満足することができなくなりますので注意してください。

ページネーション

では、キーボード、あるいはそのほかの支援技術を使用しているユーザのために、ページネーションのボタンが押された際、対応するスライドにフォーカスを戻すことを勧めています。

ユーザがこれらのナビゲーションボタンを選択した際、選択された項目に対してフォーカスを設定すべきです。このケースでは、スライダーが変化、あるいは移動した後、currentクラスを持つ<li>要素に対してフォーカスを移動する必要があります。これにより、キーボードあるいは支援技術を使用するユーザは、より簡単にスライダーを操作することができるようになります。

Splide v2にはこのような機能はありませんでしたが、v3で実装されました。下のスライダーのページネーションをクリックして、フォーカスの移動を確かめてみてください。

  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09

フォーカス可能な要素

Splideは、スライダーの表示領域に完全に収まっていないスライドに対してaria-hidden属性を割り当て、スクリーンリーダ、あるいはその他の支援技術がそれらのスライドを認識しないようにしています。ところが、スライド自体に<input><textarea>などのフォーカス可能な要素が含まれている場合、により依然として、隠れた要素にフォーカスを移動することができてしまいます。

Lighthouseがこのような不親切な要素を検出すると、以下のような警告を発し、是正を促します。

[aria-hidden="true"]が設定された要素の中にフォーカス可能な子孫要素を配置してしまうと、スクリーンリーダなどの支援技術を使用するユーザがこれらの要素を使用できなくなります。

この問題に対応するため、Splideは隠れているスライドが含む以下の要素に対してtabindex="-1"を適用し、一時的にフォーカスできないようにしています。

  • <a>
  • <button>
  • <textarea>
  • <input>
  • <select>
  • <iframe>

ほとんどの場合この対応でうまくいきますが、上記に漏れる以下の要素が含まれている場合は追加対応が必要です。

  • <area>
  • <audio controls>
  • <summary>
  • <video controls>
  • contenteditable属性が有効になっている要素
  • tabindex="0"を持った要素

どの要素に対してtabindex="-1"を適用するかは、focusableNodesオプションの値が決定しています。この値はセレクタですので、次のようにして検索対象を増やしたり、逆に不必要な要素を減らしたりすることができます。

{
focusableNodes: 'a, button, ..., area, [contenteditable]',
}
JavaScript

ただし、残念ながらtabindex="0"が設定された要素が含まれる場合、このオプションだけではうまく対応できません。これは、-1に設定した後に再びスライドが表示された際、0(あるいはその他の整数値)に戻す処理が必要になるためです。スライダーの中でtabindexを用いてフォーカスを制御することはないと信じたいですが、仮にそのような対処が必要になった場合は、visibleおよびhiddenイベントを利用すればインデックスの切り替えを実装できます。

ARIA属性

矢印のボタンやページネーションなど、インタラクション可能なすべての要素には、適切なARIA属性が割り当てられます。ただし、ラベル等に割り当てられているテキストは英語ですので、ユーザ層に合わせて適宜翻訳してください。

各スライド

矢印

また、矢印はそれ以上進めなくなった際、disabled属性が付与されます。

ページネーション

再生・停止ボタン

ナビゲーション

isNavigationオプションを有効にした場合、スライダー自身がほかのスライダーを制御するナビゲーションとしてふるまいます。このようなスライダーに対しては、リスト要素にmenuロールが、各スライドにはmenuitemロールが割り当てられます。

リスト要素

各スライド

アクティブスライドの通知

の中で唯一、を利用した「アクティブスライドの通知」には対応していません。

WAI-ARIAのライブリージョンを用いて、現在表示されている項目が何なのかをスクリーンリーダに知らせて下さい。

しかしながら、「スライダーが移動するたびに現在のスライドをリーダに読ませるとうるさい」という別の意見もあります(特に自動再生が有効な場合は顕著です)。Splide v3ではこの機能の導入を見送ることにしましたが、もし必要な場合は、以下のような拡張機能を作成することで実装することができます。

export function LiveRegion( Splide ) {
let liveRegion;
function mount() {
liveRegion = document.createElement( 'div' );
liveRegion.setAttribute( 'aria-live', 'polite' );
liveRegion.setAttribute( 'aria-atomic', 'true' );
liveRegion.classList.add( 'visually-hidden' );
Splide.root.appendChild( liveRegion );
Splide.on( 'moved', onMoved );
}
function onMoved() {
liveRegion.textContent = `Slide ${ Splide.index + 1 } of ${ Splide.length }`;
}
function destroy() {
Splide.root.removeChild( liveRegion );
}
return {
mount,
destroy,
}
}
JavaScript

この拡張機能は主に、次のようなことをしています。

  • ライブリージョンフィールドの作成
  • スライドが移動したのち、フィールドのテキストを更新

しかしこのままではテキストが表示されてしまいますので、いわゆる「視覚的に隠す」方法を用いて、スクリーンリーダには検出可能、かつ人間には見えないようにする必要があります。

.visually-hidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
CSS

Splideを初期化する際、この拡張機能を登録すれば実装完了です。

import { LiveRegion } from '...';
new Splide( '.splide' ).mount( { LiveRegion } );
JavaScript

下のスライダーを用いて結果を確認することができます。スクリーンリーダを起動し、スライダーを移動してみてください。移動が完了するたびに、リーダが現在のスライド番号を読み上げます。

  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09