About Version 4
バージョン4について
Splide v4
Splideは現在、jsDelivr(CDN)において、月間3億ヒット以上するライブラリにまで成長しました✨ この数値はカルーセルライブラリとして有名なSwiperの3倍ですので、なかなか善戦しているのではないかと思います(もちろん、ライブラリの配信方法は様々ですので、及ばないところはまだまだあります)。Splideを選んでいただいた方々、そしてスポンサーの皆様、ありがとうございます!
今回のアップデートは、前回のようにすべて書き直すという大がかりなものではありませんが、アクセシビリティを最新の要件に合わせ、より堅牢なものへと改善するための更新です。いくつかの追加機能を合わせ、以下のような修正をしました。
- W3C Carousel Design Patternに準拠しながら、アクセシビリティ周りを改修
- スクリーンリーダのためのライブリージョンを標準搭載
prefers-reduced-motion
を検知し、重要でないトランジションを無効化する処理を追加- 自動再生の再生・停止ボタンを、トグル形式に変更
- ブレークポイントを、CSSと同じふるまいになるように修正
- フリードラッグにおいて、近いスライドにスナップできるオプションを追加
- 方向をブレークポイントで切り替えられるよう
direction
オプションをレスポンシブ化 - 慣性スクロールを引き起こすマウスホイールのふるまいを制御できるようにオプションを追加
- どのブラウザでも
:focus-visible
を実現できるようにし、 テーマにスタイルを追加 - その他バグ修正
残念ながら、コードサイズは27Kb→29Kbと、2Kbほど増えました。
破壊的変更
以下の破壊的変更が既存のスライダーに影響する場合は、v3からv4への移行セクションを参照し、修正してください。
keyboard
、waitForTransition
ならびにslideFocus
の初期値を変更- 自動再生を制御するための、独立した再生・停止ボタンの機能を削除。代わりに、トグル形式を採用(再生・停止を一つのボタンで管理)
splide__slider
機能を削除し、arrows: 'slider'
およびpagination: 'slider'
を廃止- コンポーネントメソッドの一部を修正
また、新しく追加された機能に対応するため、以下の2点を更新してください(必須ではありません)。
- 新しく追加されたi18nテキストの翻訳
- 必要に応じて、
aria-label
またはaria-labelledby
をルート要素に追加
なお、インテグレーション 用パッケージを使用している場合は、それぞれの手引きを参照してください。
新しい機能について
アクセシビリティの強化
アクセシビリティをより強固で信頼できるものとするため、W3CのCarousel Design Patternに準拠するよう、ロールやARIA属性などを更新しました。また、スクリーンリーダを使用しているユーザのために、ライブリージョンを標準搭載しました。
あまり耳になじみのない言葉かもしれませんが、ライブリージョンを導入すると、動的に更新される箇所をスクリーンリーダなどの支援技術に伝えることができます。たとえば、著名なスクリーンリーダであるNVDAは、以下のようにスライドを読み上げてくれるようになります。
加えて、prefers-reduced-motion: reduced
を検知した場合、スライダーのトランジションエフェクトを無効にする処理を追加しました。これは、例えばアニメーション酔いを起こしやすいユーザや、前庭運動障害を持つユーザなどが、不要な視覚効果を なるべく抑えることを要求した際に自動で有効になります(WCAG 2.3.3)。
もしアクセシビリティの改善について詳しく知りたい場合は、こちらの長いドキュメントを参照してください。
ブレークポイント
古いバージョンでは、ブレークポイントにヒットするたびに、そのポイントに割り当てられたオプションで現在のオプションを更新していました。この場合、設定の仕方によっては、ウィンドウをリサイズした場合とページをロードした場合で、異なる結果になる可能性がありました。
例えば、次のようなオプションを考えてみます。
{
perPage
:
3
,
gap
:
'1rem'
,
breakpoints
:
{
1200
:
{
perPage
:
2
,
gap
:
'1rem'
}
,
640
:
{
gap
:
0
}
,
}
,
}
JavaScript
{ perPage : 3, gap : '1rem', breakpoints: { 1200: { perPage: 2, gap: '1rem' }, 640 : { gap: 0 }, }, }
1200px以上のデバイスでこのページを開いたとき、スライダーは3枚のスライドを表示します。そのままウィンドウサイズを640pxまで狭めると、1200: { perPage: 2 }
を通過しますのでスライドは2枚に減ります。ところが、初めから640px以下の状態でページを開くと、スライドは2枚ではなく3枚表示されます。
意図通りの正しい結果を得るには次のように、どのポイントにも更新したいオプションを設定しておく必要がありました。
{
perPage
:
3
,
gap
:
'1rem'
,
breakpoints
:
{
1200
:
{
perPage
:
2
,
gap
:
'1rem'
}
,
640
:
{
perPage
:
2
,
gap
:
0
}
,
}
,
}
JavaScript
{ perPage : 3, gap : '1rem', breakpoints: { 1200: { perPage: 2, gap: '1rem' }, 640 : { perPage: 2, gap: 0 }, }, }
バージョン4では下記のような理由により、CSSのメディアクエリと同じふるまいをするよう修正しました。
- CSSとの混同を防げる
- ウィンドウサイズ変更とページロードで、必ず同じ結果になる
- どのオプションが使用されるか、直観的にわかりやすい
この変更により、現在のウィンドウサイズに該当するすべてのブレークポイントのオプションが、順次ベースオプションにマージされます。たとえば、
{
arrows
:
true
,
perPage
:
3
,
breakpoints
:
{
1200
:
{
arrows
:
false
}
,
800
:
{
perPage
:
2
}
,
640
:
{
}
,
}
,
}
JavaScript
{ arrows : true, perPage: 3, breakpoints: { 1200: { arrows: false }, 800 : { perPage: 2 }, 640 : {}, }, }
のようなオプションを640px以下のデバイスで開いた場合、1200
および800
も条件を満たすため、スライドの枚数は2枚になり、矢印は無効化されます。
さらに、条件を満たさなくなったポイントのオプションは、ベースオプションで指定しない限り初期値にリセットされます。たとえば、ある特定のポイントでスライドの幅を指定したとします。
{
breakpoints
:
{
1200
:
{
fixedWidth
:
200
}
,
}
,
}
JavaScript
{ breakpoints: { 1200: { fixedWidth: 200 }, }, }
ウィンドウ幅が1200px以下のとき、スライドは200pxで表示されますが、幅を大きくしていき1200pxを超えると、スライドの幅は初期値にリセットされundefined
の状態に戻ります。
古いバージョンのブレークポイントは新しいものよりも厳密な設定を要求していたため、今回の変更によって既存のスライダーが壊れることはないと思いますが、アップグレードの際は念のため動作確認を行ってください。
v3からv4への移行
オプション
いくつかのオプションは、初期値が変更されています。状況にあわせ、適宜更新してください。
keyboard
初期値をtrue
からfalse
に変更しました。また、'focused'
の際、tabindex
をルート要素に追加する機能は廃止しました。
true | スライダー内の要素がフォーカスを持っている場合にのみショートカットを有効にする |
---|---|
false | ショートカットを無効にする |
'global' | windowの |
'focused' |
|
詳しくはアクセシビリティに記載があります。
waitForTransition
初期値をtrue
からfalse
に変更しました。2つの同期したスライダーを作成した場合、このオプションが同期を妨げるという不親切さへの対処です。
slideFocus
もとはtrue
でしたが、新しいバージョンでは以下のように初期値が決定されます。
- 通常は
false
isNavitation
が有効な場合true
ほかのアクセシビリティ関連の改善の結果、積極的にこのオプションを有効にする必要は「おそらく」ないと思います(現段階では、まだ確信を持てていません)。一方、isNavigation
が有効の場合は、このオプションは有効である必要があります。これは、「クリックできる要素は、フォーカス可能なインタラクティブ要素でなければならない」という(かなり悩ましい)指針が存在するためです。
arrows
値に'slider'
は指定できなくなりました。true
に変更したうえで、このガイドに従って修正してください。
pagination
値に'slider'
は指定できなくなりました。true
に変更したうえで、このガイドに従って修正してください。
i18n
新しく、carousel
、slide
およびslideLabel
が追加されました。このページに詳細が記載されています。
再生・停止ボタン
利用者からのフィードバックにより、分離された再生・停止ボタンよりも、単一のトグルボタンのほうが需要が高いことがわかりました。今回のバージョンから分離式は廃止されましたので、次のようにしてトグルボタンに置き換えてください。
----++++<
div
class
=
"splide"
>
...
<
div
class
=
"splide__autoplay"
>
<
button
class
=
"splide__play"
>
Play
<
/
button
>
<
button
class
=
"splide__pause"
>
Pause
<
/
button
>
<
/
div
>
<
button
class
=
"splide__toggle"
type
=
"button"
>
<
span
class
=
"splide__toggle__play"
>
Play
<
/
span
>
<
span
class
=
"splide__toggle__pause"
>
Pause
<
/
span
>
<
/
button
>
<
/
div
>
HTML
<div class="splide"> ... - <div class="splide__autoplay"> - <button class="splide__play">Play</button> - <button class="splide__pause">Pause</button> - </div> + <button class="splide__toggle" type="button"> + <span class="splide__toggle__play">Play</span> + <span class="splide__toggle__pause">Pause</span> + </button> </div>
以下のようにすれば、引き続き個別のボタンを使用できます。
var
splide
=
new
Splide
(
'.splide'
,
{
autoplay
:
true
}
)
.
mount
(
)
;
var
Autoplay
=
splide
.
Components
.
Autoplay
;
var
play
=
splide
.
root
.
querySelector
(
'.splide__play'
)
;
var
pause
=
splide
.
root
.
querySelector
(
'.splide__pause'
)
;
if
(
play
)
{
play
.
addEventListener
(
'click'
,
function
(
)
{
Autoplay
.
play
(
)
;
}
)
;
}
if
(
pause
)
{
pause
.
addEventListener
(
'click'
,
function
(
)
{
Autoplay
.
pause
(
)
;
}
)
;
}
JavaScript
var splide = new Splide( '.splide', { autoplay: true } ).mount(); var Autoplay = splide.Components.Autoplay; var play = splide.root.querySelector( '.splide__play' ); var pause = splide.root.querySelector( '.splide__pause' ); if ( play ) { play.addEventListener( 'click', function () { Autoplay.play(); } ); } if ( pause ) { pause.addEventListener( 'click', function () { Autoplay.pause(); } ); }
スライダー要素
スライダー要素(<div class="splide__slider">
)は、トラックをrelative
な要素で囲む目的で導入されていました。新しいバージョンでは、HTMLの構成に対する制約を緩めたため、この要素の必要性はなくなりました。同様の結果を得るためには、次のようにします。
arrows
とpagination
オプションの値を'slider'
からtrue
に変更します-+-+{
arrows
:
'slider'
,
arrows
:
true
,
// または削除
pagination
:
'slider'
,
pagination
:
true
,
// または削除
}
JavaScript{ - arrows: 'slider', + arrows: true, // または削除 - pagination: 'slider', + pagination: true, // または削除 }
- スライダー要素を、
position: relative
を持った任意の<div>
で置き換えます<
div
class
=
"splide"
>
<
div
style
=
"position: relative"
>
<
div
class
=
"splide__track"
>
<
div
class
=
"splide__list"
>
...
<
/
div
>
<
/
div
>
<
/
div
>
<
/
div
>
HTML<div class="splide"> <div style="position: relative"> <div class="splide__track"> <div class="splide__list">...</div> </div> </div> </div>
もしくは.splide__slider
を独自で定義すれば、これまでのマークアップをそのまま使用できます。
.splide__slider
{
posiiton
:
relative
;
}
CSS
.splide__slider { posiiton: relative; }
コンポーネント
Move#isBusy()
Controller#isBusy()
に移動しました。
Controller#scroll()
引数が変わりました。詳しくはControllerを参照してください。
Scroll#scroll()
引数が変わりました。詳しくはScrollを参照してください。