Splide.jsで自動再生の切り替えボタンを作る2つの方法

はじめに

Splide.jsはアクセシビリティと軽量性を両立したスライダーライブラリです。標準で備わっているオートプレイ機能を、ユーザー操作で停止・再開できるようにしておくと、閲覧体験の制御を読者側に委ねられます。

本記事は、Splide.jsの自動再生をボタンで切り替える方法を、1つのボタンで開閉する基本パターンと、ON/OFFを別々のボタンに分ける応用パターンの2通りで紹介します。

動作確認はSplide.js v4.1系で行っています。CDNから読み込む構成で例示しますが、npm経由でESMとして読み込む環境でも同じAPIで動きます。

Splide.jsのオートプレイの基本

オートプレイはオプションにautoplay: trueを渡すと有効になります。挙動の制御にはAutoplayコンポーネントが用意されており、play()pause()の2つのメソッドで再生状態を切り替えられます。

イベント側は、再生・停止の遷移時にautoplay:playautoplay:pauseが発火します。ボタンの表示やaria-pressedの更新は、これらのイベントを購読する側にまとめて書くと、初期化時や外部要因(マウスホバーやフォーカスでの一時停止)の変化にも自然に追従できます。

autoplayオプションにはtrueのほかに'pause'という値もあります。'pause'を渡すとオートプレイのコンポーネントは読み込まれるものの、初期状態は停止になります。「ユーザーが任意で再生する」前提のスライダーで便利です。

共通の準備

両パターンで共通して使うHTMLとCSS、Splide.jsの読み込みを先にまとめます。

HTML

HTML
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css">

<section class="splide js-slider" aria-label="ギャラリー">
  <div class="splide__track">
    <ul class="splide__list">
      <li class="splide__slide"><img src="/img/01.jpg" alt=""></li>
      <li class="splide__slide"><img src="/img/02.jpg" alt=""></li>
      <li class="splide__slide"><img src="/img/03.jpg" alt=""></li>
    </ul>
  </div>
</section>

<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/js/splide.min.js"></script>

splideクラスはSplide.jsの仕様で必須です。スクリプトから対象を取りやすくするために、JS操作用のjs-sliderクラスを別に付けています。

CSS

CSS
.slider-controls {
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
}

.slider-controls__button {
  padding: 0.5rem 1rem;
  border: 1px solid currentColor;
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
}

.slider-controls__button[aria-pressed="true"] {
  background: #222;
  color: #fff;
}

.slider-controls__button[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

ボタンの押下状態はaria-pressed、無効化はdisabled属性で表現します。スタイルは属性セレクタで揃えると、状態とCSSがズレにくくなります。

1つのボタンで切り替える方法

最初のパターンは、1つのボタンで再生と停止を交互に切り替えるシンプルな構成です。再生中は「停止」、停止中は「再生」とラベルが入れ替わります。

See the Pen Splide.js v1 by watanabe (@web-sourcecode) on CodePen.

HTML

HTML
<section class="splide js-slider" aria-label="ギャラリー">
  <!-- splide__track 以下は共通の準備と同じ -->
</section>

<div class="slider-controls">
  <button type="button"
          class="slider-controls__button js-autoplay-toggle"
          aria-pressed="true">
    <span class="js-autoplay-toggle-label">停止</span>
  </button>
</div>

aria-pressedはボタンの押下状態を表す属性で、trueが現在オートプレイON、falseがOFFを示します。スクリーンリーダーが状態を読み上げてくれるため、ラベルの変化と合わせて使うと挙動が伝わりやすくなります。

JavaScript

JavaScript
const splide = new Splide('.js-slider', {
  type: 'loop',
  autoplay: true,
  interval: 4000,
  pauseOnHover: false,
  pauseOnFocus: false,
});

splide.mount();

const toggleButton = document.querySelector('.js-autoplay-toggle');
const toggleLabel = toggleButton.querySelector('.js-autoplay-toggle-label');
const Autoplay = splide.Components.Autoplay;

// クリックで再生・停止を切り替える
toggleButton.addEventListener('click', () => {
  const isPlaying = toggleButton.getAttribute('aria-pressed') === 'true';
  if (isPlaying) {
    Autoplay.pause();
  } else {
    Autoplay.play();
  }
});

// 状態の反映はイベント購読側にまとめる
splide.on('autoplay:play', () => {
  toggleButton.setAttribute('aria-pressed', 'true');
  toggleLabel.textContent = '停止';
});

splide.on('autoplay:pause', () => {
  toggleButton.setAttribute('aria-pressed', 'false');
  toggleLabel.textContent = '再生';
});

ポイントは「状態の更新はイベント側でまとめて行う」ことです。クリックハンドラ内で直接aria-pressedやラベルを書き換えると、ライブラリ側が別の理由で再生を止めたとき(後述のpauseOnHoverなど)に表示と実態がズレます。autoplay:playautoplay:pauseを購読しておけば、外部要因による変化にも自然に追従できます。

pauseOnHoverpauseOnFocusは、デフォルトでマウスホバーやフォーカスで自動再生を一時停止します。ユーザーがボタンで明示的に制御する想定であれば、両方をfalseにしておくと挙動が読みやすくなります。スライダー上にリンクやボタンが乗っている場合はpauseOnFocus: trueのままが親切です。

2つのボタンでON/OFFを切り替える方法

2つ目のパターンは、再生用と停止用のボタンを別々に置く構成です。1つのボタンで両方の役割を兼ねるより、操作の意味が直感的に伝わります。再生中は「再生」ボタンが押し込まれた状態で表示され、押せるのは「停止」だけ、というリモコン的な見た目にできます。

See the Pen Splide.js v1 by watanabe (@web-sourcecode) on CodePen.

HTML

HTML
<div class="slider-controls" role="group" aria-label="自動再生の制御">
  <button type="button"
          class="slider-controls__button js-autoplay-on"
          aria-pressed="true"
          disabled>
    再生
  </button>
  <button type="button"
          class="slider-controls__button js-autoplay-off"
          aria-pressed="false">
    停止
  </button>
</div>

2つのボタンで1つの状態を切り替える構成のため、role="group"でひとまとまりであることを示します。aria-pressedは両方のボタンに付け、片方がtrueのときもう一方はfalseになる前提で運用します。

JavaScript

JavaScript
const splide = new Splide('.js-slider', {
  type: 'loop',
  autoplay: true,
  interval: 4000,
  pauseOnHover: false,
  pauseOnFocus: false,
});

splide.mount();

const onButton = document.querySelector('.js-autoplay-on');
const offButton = document.querySelector('.js-autoplay-off');
const Autoplay = splide.Components.Autoplay;

onButton.addEventListener('click', () => {
  Autoplay.play();
});

offButton.addEventListener('click', () => {
  Autoplay.pause();
});

// 状態反映を一カ所にまとめる
const reflectState = (isPlaying) => {
  onButton.setAttribute('aria-pressed', String(isPlaying));
  offButton.setAttribute('aria-pressed', String(!isPlaying));
  onButton.disabled = isPlaying;
  offButton.disabled = !isPlaying;
};

splide.on('autoplay:play', () => reflectState(true));
splide.on('autoplay:pause', () => reflectState(false));

ボタン側のクリック処理はAutoplay.play()Autoplay.pause()を呼ぶだけに保ち、表示の更新はイベント購読側にまとめています。1つ目のパターンと同じく、ライブラリ側で状態が変わったときも表示がズレません。

disabledを切り替えているのは、現在の状態と同じボタンを連打させないためです。再生中に「再生」ボタンを押せても挙動は何も変わりません。デザイン上の制約でdisabledを使えない場合は、aria-pressedの見た目だけで状態を区別する選択肢もあります。

実装時の注意点

Splideコンストラクタを呼んでも、mount()を実行するまでComponents.Autoplayは使えません。ボタンのイベントを登録するのはmount()を呼んだ後に行います。

autoplayオプションをtrueにしている場合、Splide.js本体は読み込み完了後すぐに再生を始めます。「最初は停止状態でユーザーがクリックしたら動かす」フローにしたい場合は、autoplay: 'pause'を指定するとオートプレイのコンポーネントは読み込みつつ初期状態を停止にできます。

オートプレイは見ているユーザーの注意を引き続けるUIです。アクセシビリティの観点では、ユーザーが任意のタイミングで停止できる手段を提供することが推奨されています。今回の切り替えボタンはこの要件を満たすための基本にあたります。

動きに敏感な方への配慮として、prefers-reduced-motionが指定されている環境では既定で停止状態にする選択肢もあります。メディアクエリの判定をJavaScript側で読み取り、初期のautoplayオプションを切り替える書き方が確実です。

JavaScript
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

const splide = new Splide('.js-slider', {
  type: 'loop',
  autoplay: prefersReduced ? 'pause' : true,
  interval: 4000,
});
splide.mount();

CSS側でも、スライドの遷移そのものを抑える指定を併用しておくと安心です。

CSS
@media (prefers-reduced-motion: reduce) {
  .splide__list {
    transition: none !important;
  }
}

まとめ

Splide.jsのオートプレイ制御は、Components.Autoplayplay()pause()、対応するイベントautoplay:play/autoplay:pauseの組み合わせで完結します。1つのボタンで切り替える構成はコードが短く、UIスペースを節約したいケースに向きます。2つのボタンに分ける構成は操作の意味が伝わりやすく、現在の状態をUIから読み取りやすくなります。

どちらの構成でも、表示の更新はイベント購読側にまとめると外部要因での状態変化に追従できます。次にスライダーを設置するときは、自動再生のON/OFFボタンとprefers-reduced-motionへの配慮までセットで設計に入れておくと、後から手戻りが少なく済みます。

ポイント

  • オートプレイ制御はsplide.Components.Autoplay.play()pause()で行う
  • 表示の更新はautoplay:play/autoplay:pauseイベントの購読側に集約する
  • aria-pressed属性で押下状態を伝え、スクリーンリーダーへの配慮を入れる
  • prefers-reduced-motionが指定されている環境では初期値を'pause'に切り替える

参考リンク

read next