流れ続けるカルーセルの実装、Splide・GSAP・CSSをどう使い分けるか

下記のような流れ続けるカルーセル(スライダー)を実装しようとしたとき、カルーセルのライブラリを使うべきか、GSAPにすべきか、CSSアニメーションだけで済ませるか迷った経験はないでしょうか。私は結構な頻度で迷います。

流れ続けるカルーセル

そこで、自分なりの指針を整理してみることにしました。この記事では自動で流れ続けるカルーセルの個人的な実装方針について書き留めています。

結論

私は実務では以下のように使い分けることが多いです。

  • ユーザーのアクションが入る場合:カルーセルライブラリ(Splide)
  • スクロールに連動して動かす場合:アニメーションライブラリ(GSAP)
  • 上記以外:CSSアニメーション

表にまとめると次のようになります。

SplideGSAPCSSアニメーション
適している例スワイプ・ページ送り・一時停止などのユーザー操作があるスクロールに連動して速度・方向等が変わるシンプルな自動スクロール、斜め方向など

それぞれの実装パターンについて個別に見ていきます。

カルーセルライブラリを使用するケース

今回はSplideを使用しました。

npmでインストールするか、下記のようにCDNからファイルを参照します。

<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/js/splide.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide-core.min.css" rel="stylesheet">

今回のような自動スクロールを導入する場合にはAuto Scrollのエクステンションが必要です。

<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide-extension-auto-scroll@0.5.3/dist/js/splide-extension-auto-scroll.min.js"></script>

下記が実装例です。

Splideで実装した流れ続けるカルーセル

カルーセルライブラリで導入したスライダーの特徴としては、ユーザー操作の実装をスムーズに行える点です。上記の例では左右にスワイプができ、「前へ」「次へ」のページ送りのボタンが機能するようにオプションを設定しています。

オプションの設定例
const options = {
type: "loop",
autoWidth: true,
gap: "10px",
pagination: false,
arrows: true, // 前へ・次へのページ送りを表示するかどうか(デフォルトでture)
drag: true, // ドラッグによりスライダーを動かせるかどうか(デフォルトでture)
autoScroll: {
speed: 0.7,
pauseOnFocus: false,
pauseOnHover: false,
},
};

Splideではアクセシビリティについても一定程度担保してくれるのが良い点です。

デメリットとしては、ライブラリの仕様に縛られるため、複雑なカスタマイズを行おうとするとコストがかかります。またカスタマイズによっては実装困難な場合があります。

例えばSplideでは斜め方向に自動スクロールさせようとtransform: rotate(45deg);を記述すると、表示が崩れます。これはSplideが内部でtransformを使ってスライドの位置を制御しているため、外側からrotateを重ねると競合してしまうためです(Swiperでは問題なさそうでした)。

メリット・デメリットをまとめると次のようになります。

メリットデメリット
  • スワイプやページ送り、一時停止の導入が簡単
  • アクセシビリティを担保できる
  • ライブラリを読み込む必要がある
  • カスタマイズには限界がある

実際の使用例としては、採用ページによくある「数字で見るXXX」をカード形式のスライドとして見せる場合に、カルーセルライブラリを使用するようにしています。

アニメーションライブラリを使用するケース

次にアニメーションライブラリを使用するケースです。今回はGSAPを使用しました。

こちらもnpmでインストールするか、下記のようにCDNからファイルを参照します。後ほどスクロールに連動した動きを実装するため、ScrollTriggerも読み込んでいます。

<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.1/dist/ScrollTrigger.min.js"></script>

まずはシンプルな流れ続けるカルーセルを実装しました。

GSAPで実装した流れ続けるカルーセル

GSAPの特徴としてはとても少ない量のコードで実装できる点があります。上記の例ではわずか7行のJavaScriptのコードで動いています。

script.js
const lists = gsap.utils.toArray('[data-infinite-carousel="list"]');
const loop = gsap.to(lists, {
xPercent: -100,
ease: "none",
duration: 30,
repeat: -1,
});

そしてGSAPが得意なスクロール連動の動きも実装することができます。次の例ではスクロールの速度(強度)に応じて、スライダーの動く速度も早くなるように実装しています。

スクロール速度に応じて移動スピードが変わるカルーセル

近年のWebサイトでよく見かける動きですよね。他にスクロールの方向に応じてスライドが移動する向きを反転させる動きも見かけることが多いです。

GSAPでカルーセルを実装するデメリットとしては、ドラッグ操作やページ送りなどのユーザー操作には不向きな点です。GSAPはあくまでもアニメーションに関する動きを制御するだけなので、ユーザー操作を実現するには全て自前で実装する必要があります。

メリット・デメリットをまとめると次のようになります。

メリットデメリット
  • スクロールに連動したアニメーションを容易に実装できる
  • 柔軟にアニメーションをカスタマイズできる
  • ライブラリを読み込む必要がある
  • ユーザー操作は自前で実装する必要がある

スクロール連動やリッチな動きが求められる場合は、GSAPで実装するのが最も適しています。

CSSアニメーションを使用するケース

最後にCSSアニメーションを使用するケースです。HTMLとCSSのみで完結するため、ライブラリを読み込む必要はありません。下記が実装例です。

CSSで実装した流れ続けるカルーセル

最大のメリットはコード量が少なくシンプルなことでしょう。画像(スライド)のリストを横並びにし、translateが変化する@keyframesを設定するのみで機能します。

style.css
.c-infinite-carousel {
display: flex;
overflow: hidden;
}
.c-infinite-carousel__list {
display: flex;
animation: infinity-scroll-from-left 30s infinite linear;
}
@keyframes infinity-scroll-from-left {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}

画像(スライド)のリストをtranslateで移動させているだけなので、次のような斜め方向への無限スクロールも簡単に実装できます。以下はtransform: rotate(-20deg);を設定した作例です。

CSSで実装した斜め方向に流れ続けるカルーセル

デメリットとしてはリストの境目で、カクつきが発生しやすいことです。特に要素間の余白をcolumn-gapで設定しているとカクつきが発生しやすい印象です。

column-gapでカクつきが発生しやすい理由は、translateX(-100%)の基準となる幅の計算にあります。translateX(-100%)はその要素自身の幅を基準に移動量を計算しますが、column-gapで設定した余白はその幅に含まれません。そのため、アニメーションがループして最初の位置に戻る際に、余白分だけ位置がずれてカクつきが発生します。

一方でmarginで余白を設定した場合は、余白を含めた位置の計算がtranslateX(-100%)と一致しやすくなるため、ループ時のずれが発生しにくくなります。

style.css
/*
カクつきが発生しやすいコード例
*/
.c-infinite-carousel {
display: flex;
overflow: hidden;
/* column-gapでリスト間の余白を設定 */
column-gap: 10px;
}
.c-infinite-carousel__list {
display: flex;
/* column-gapでスライド間の余白を設定 */
column-gap: 10px;
animation: infinity-scroll-from-left 30s infinite linear;
}
.c-infinite-carousel__item {
width: 200px;
aspect-ratio: 1;
}
/*
カクつきを抑えたコード例
*/
.c-infinite-carousel {
display: flex;
overflow: hidden;
}
.c-infinite-carousel__list {
display: flex;
animation: infinity-scroll-from-left 30s infinite linear;
}
.c-infinite-carousel__item {
/* margin-leftで余白を設定 */
margin-left: 10px;
width: 200px;
aspect-ratio: 1;
}

メリット・デメリットをまとめると次のようになります。

メリットデメリット
  • HTMLとCSSのみで完結でき管理が容易
  • JavaScriptライブラリが不要で軽量
  • 斜め方向の動きにも対応できる
  • カクつきが発生することがある
  • 複雑な動きに対応しようとするとCSSのみでは困難

近年登場したCSS カルーセル機能を使用すれば、一般的なユーザー操作についてはCSSのみで実装することも可能なようです。ただし未実装のブラウザもあるため、実務で使用するにはまだ先になりそうです。

まとめ

流れ続けるカルーセルの実装方法を3パターン見てきました。それぞれ適しているケースが異なるため、仕様が決まった段階で実装方法を選べると、無駄な手戻りを減らせると感じています。

今回は「流れ続けるカルーセル」に絞った話でしたが、カルーセル以外のUIコンポーネントについても同様に自分なりの判断基準を整理していきたいと思っています。

この記事を書いた人

写真:ブール 代表 西川雅人

Masato Nishikawa

ウェブ制作の現場でコーディングパートナーとして活動しているコーダーです。実務で得た知見やノウハウを、このブログで発信しています。

コーディングや
WordPress実装の
ご相談を承っています。

新規制作から運用フェーズの修正まで柔軟に対応します。
お見積りや実装可否の確認など、お気軽にご連絡ください。