Splideの自動再生が、矢印を押すと止まったままになる|原因は最初からオンのpauseOnFocusとpauseOnHover

こんにちは、ゆきしょうです。
Splideで作ったスライダーで、矢印を押したあと、自動送りが止まったまま動かなくなりました。
原因は、Splideで最初からオンになっているpauseOnFocusとpauseOnHoverでした。
pauseOnFocusは、マウスで押した矢印に残る「選ばれた状態」でも止まります。
pauseOnHoverは、マウスがスライダーの箱の上にあるあいだ止まります。
その箱が画面の幅いっぱいあったので、矢印から少し外したくらいでは止まったままでした。
建設会社のサイトの、社員紹介のスライダーで起きたことと直し方を書きます。
自動送りは5秒にした
スライダーを自動で送るようにしたとき、最初は4秒にしていました。
カードには社員のキャッチと名前の文字も載っています。
文字が載っているので5秒がよいと、AIに勧められて延ばしました。
Splideは、何も指定しなければ5秒(interval: 5000)で送ります。
アクセシビリティの指針のWCAGには、動きについての決まりがあります。
自動で始まり、5秒より長く続き、ほかの内容と並んで出る動きには、一時停止・停止・非表示の手段を用意します。
動きが欠かせないものは除かれます。
ずっと送り続けるスライダーは、自動で始まり、止めない限り動き続けます。
このスライダーには、自動で送るようにした最初から、止めるボタンを付けていました。
WCAG 2.2 Understanding 2.2.2: Pause, Stop, Hide(W3C)
マウスを外しても、自動送りが止まったままだった
5秒にしてと頼んだとき、マウスを上に乗せると止まり、外しても動き出さないことにも気づいていました。
コードを書いていたAIに「外したらまた動くようにして」と頼み、直ったと報告を受けました。
そのあと自分で矢印を押して送ってみると、マウスを外しても、やはり動きません。
AIの確認では、マウスをスライダーの箱の外まで出して測っていました。
矢印のすぐ横へ外す動きは、確かめられていませんでした。
pauseOnFocusとpauseOnHoverが、どちらも最初からオンだった
Splideの設定一覧では、pauseOnHoverもpauseOnFocusも、最初からtrueです。
どちらも、アクセシビリティのためにtrueにしておくよう書かれています。
マウスで押した所に残る「選ばれた状態」(pauseOnFocus)
pauseOnFocusは、スライダーの中に選ばれた要素があるあいだ、自動送りを止める設定です。
矢印やカードをマウスで押すと、その部分が選ばれた状態のまま残ります。
そのため、矢印を押したあとは、マウスを外しても止まったままでした。
画面の幅いっぱいの箱(pauseOnHover)
pauseOnHoverは、マウスがスライダーの上にあるあいだ、自動送りを止める設定です。
上にあるかどうかは、スライダー全体の箱で判断されます。
このスライダーの箱は画面の幅いっぱいで、高さが740pxありました。
矢印から少し横へマウスを動かしても、まだ箱の中にいます。
矢印の300px右へ外すと、7秒たっても動きませんでした。
箱の外まで出すと、動き出しました。
止めるのは「カードと矢印に乗っている間」と「キーボードで選んだとき」だけにした
pauseOnHoverとpauseOnFocusはfalseにして、止める条件を自分で書きました。
import Splide from "@splidejs/splide";
const root = document.querySelector(".js-staff-splide");
if (root) {
const splide = new Splide(root, {
type: "loop",
autoplay: true,
interval: 5000,
pauseOnHover: false,
pauseOnFocus: false,
});
splide.mount();
const autoplay = splide.Components.Autoplay;
const toggle = root.querySelector(".splide__toggle");
const HOVER_TARGET = ".top-staff__link, .splide__arrow";
let hovered = false;
let keyboardFocus = false;
const sync = () => {
if (hovered || keyboardFocus) {
autoplay.pause(false);
return;
}
const stoppedByUser = toggle && !toggle.classList.contains("is-active");
if (!stoppedByUser) autoplay.play();
};
root.addEventListener("pointerover", event => {
if (event.pointerType !== "mouse") return;
hovered = Boolean(event.target.closest(HOVER_TARGET));
sync();
});
root.addEventListener("pointerleave", () => {
hovered = false;
sync();
});
root.addEventListener("focusin", event => {
if (!event.target.matches(":focus-visible")) return;
keyboardFocus = true;
sync();
});
root.addEventListener("focusout", event => {
if (!keyboardFocus || root.contains(event.relatedTarget)) return;
keyboardFocus = false;
sync();
});
}マウスで止めるのは、カードか矢印の上にあるときだけです。
コードでは、.top-staff__link と .splide__arrow がそれに当たります。
カードの間のすき間へ外せば、また動き出します。
キーボードで選んだかどうかは、:focus-visibleで見分けています。
MDNには、ボタンをマウスでクリックした場合、一般にフォーカスは表示されないと書かれています。
なので、マウスで押した矢印では止まらず、キーボードで選んだときだけ止まります。
直したあと、矢印を押して横のすき間へ外すと、約5.6秒後に次のカードへ進みました。
自動送りを付けるなら、止めるボタンも付ける
Splideの自動再生のガイドにも、自動再生を使うなら再生・停止のボタンも用意するよう書かれています。
このスライダーにも、止めるボタン(.splide__toggle)を付けました。
デザインの見本には無いボタンだったので、キーボードで選んだときだけ見えるようにしています。
マウスだけで使う人には、このボタンは見えません。
止めるボタンで止めた人には、マウスを外しても自動送りを再開しません。
コードのstoppedByUserが、その見分けです。
動きを減らす設定(prefers-reduced-motion)をしている人には、Splideは自動送りを始めません。
reducedMotionという設定の初期値で、そうなっています。
ただし、上のコードはマウスを外すとplay()を呼びます。
play()は、Splide側の止まった印を消して動き出します。
なので、動きを減らす設定の人が止まったままでいられるのは、止めるボタンがあるときだけです。
止めるボタンを付けないなら、play()の前にprefers-reduced-motionも確かめてください。
AIが書いたコードでも、止まるのを見つけるのは触る人
このスライダーのコードは、私が指示して、AI(Claude Code)が書きました。
AIは、何を確かめたかを秒数つきで報告してくれます。
それでも、矢印を押してすぐ横へ外す動きは、私が触るまで試されていませんでした。
自動送りを付けたら、マウスでもキーボードでも、押して、外して、また動くかを自分の手で確かめてみてください。
Web制作を独学した記録は、こちらに書きました。
以上、Splideの自動再生が、矢印を押すと止まったままになる原因と直し方でした。





