ウェブ制作ではカルーセル(スライドショーとも呼びます)はよく利用されるユーザーインターフェイスです。複数のバナーをスペースを節約してレイアウトできるので、情報を整理しやすく、訴求しやすいといった利点があります。
カルーセルをウェブで実装するにはJavaScriptが欠かせませんが、自力でゼロから実装すると想像以上に大変なものです。そのため、JavaScriptライブラリを採用することが制作現場では多いです。数多くのJSライブラリが存在しますが、著者がピックアップした3種類のライブラリを比較紹介します。
紹介するJSライブラリ
次の3種類のライブラリを紹介します。
それぞれのJSライブラリについて、ファイルサイズやTypeScriptのサポート状況などを比較表としてまとめました。
Slick.js | Swiper.js | keen-slider.js | |
---|---|---|---|
ファイルサイズ | 約52KB | 約150KB | 10KB |
依存ライブラリ | jQuery | Dom7 (内部で使用) |
- |
CDN | ◯ | ◯ | ◯ |
npm | ◯ | ◯ | ◯ |
TypeScriptのサポート | 非公式 | ◯ | ◯ |
React, Vue, Angular | 非公式 | ◯ | ◯ |
a11yのサポート | ◯ | ◯ | - |
ナビゲーション (前後へスライドするボタンなど) |
◯ | ◯ | - |
いずれもMITライセンスで公開されていますので、個人・商用問わず利用可能です。
Slick.js
Slick.jsは簡潔なコードで実装できるのが特徴のモバイルフレンドリーなカルーセルライブラリです。機能は少なめですが、ナビゲーションや表示するスライド数を変更するといった基本的な機能は備わっています。jQueryプラグインのため実装にはjQueryを読み込む必要があります。タッチ・スワイプ操作にも対応しています。ReactやVue向けのモジュール、TypeScriptのサポートは公式で提供されていませんがOSSで存在します。
このJSライブラリの基本的な実装と、アニメーションをフェードに変えた作例を用意しました。
基本の作例
<div class="slick carousel">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
$(document).ready(() => {
$(".slick").slick({
infinite: true, // ループの有効化
dots: true, // ドットインジケーターの表示
});
});
アニメーションをフェードに変えた作例
アニメーションをフェードに切り替えたい場合は、fade
プロパティを有効化します。有効化すると、スワイプ中にアニメーションが発生しなくなるため注意が必要です。
(上述の作例とHTMLコードは同じ)
$(document).ready(() => {
$(".slick").slick({
infinite: true, // ループの有効化
dots: true, // ドットインジケーターの表示
fade: true, // フェードアニメーションを有効化
});
});
Swiper.js
Swiper.jsはタッチパネルのデバイスで使われることを重点においているカルーセルライブラリです。Slick.jsと同様に、タッチ・スワイプ操作にも対応しています。エフェクトモジュールを使用して、簡単に多彩な表現ができるのが大きな特徴です。機能が豊富なため容量も大きいですが、ES Modulesのimport文でモジュールを絞ったインポートができるので工夫次第で容量を節約できます。
多くのイベントが準備されているため、さまざまな表現に柔軟に対応できます。今も更新が頻繁に行われているためバージョンアップのサイクルが早いことも特徴です。
依存ライブラリについては、同じ作者が開発されているDom7というJSライブラリが使われていますが、Swiper.jsに内蔵されているためとくに意識する必要はありません。
このJSライブラリの基本的な実装と、エフェクトモジュールを利用した作例をいくつか用意しました。
基本の作例
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div>1</div>
</div>
<div class="swiper-slide">
<div>2</div>
</div>
<div class="swiper-slide">
<div>3</div>
</div>
</div>
<div class="swiper-pagination"></div>
<button type="button" class="swiper-button-prev"></button>
<button type="button" class="swiper-button-next"></button>
</div>
const swiper = new Swiper(".swiper-container", {
// ドットインジケーターの表示
pagination: {
el: ".swiper-pagination",
},
// 前後スライドボタンを表示
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
loop: true, // ループの有効化
});
フェードエフェクトを使用した作例
(上述の作例とHTMLコードは同じ)
const swiper = new Swiper(".swiper-container", {
/* ドットインジケーター、前後ボタン、ループの記述は省略 */
effect: "fade",
fadeEffect: {
crossFade: true
},
});
カバーフローエフェクトを使用した作例
(上述の作例とHTMLコードは同じ)
const swiper = new Swiper(".swiper-container", {
/* ドットインジケーター、前後ボタン、ループの記述は省略 */
slidesPerView: 1.6, // 表示するスライドの枚数
centeredSlides : true, // スライドを中央揃えを有効化
effect: "coverflow",
coverflowEffect: {
rotate: 0, // スライドの回転角度
stretch: 50, // スライドの間隔(px単位)
depth: 200, // 奥行きの設定(translateをZ方向にpx単位で移動)
modifier: 1, //
slideShadows : true, // 先頭スライドのbox-shadowを有効化
},
});
カードエフェクトを使用した作例
(上述の作例とHTMLコードは同じ)
const swiper = new Swiper(".swiper-container", {
/* ドットインジケーター、前後ボタン、ループの記述は省略 */
grabCursor: true,
effect: "cards",
});
クリエイティブエフェクトを使用した作例
クリエイティブエフェクトは表示しているスライドの移動先と、次に表示されるスライドのCSSプロパティをいくつか操作できます。このサンプルでは、前後のスライドがアニメーションされる時のtransform: translate()
を操作しています。
(上述の作例とHTMLコードは同じ)
const swiper = new Swiper(".swiper-container", {
/* ドットインジケーター、前後ボタン、ループの記述は省略 */
grabCursor: true,
effect: "creative",
creativeEffect: {
prev: { // 表示しているスライドの移動先
shadow: true, // 影の有効化
translate: [0, 0, -400], // translateをX,Y,Zで指定
},
next: { // 次に表示されるスライドの設定
translate: ["100%", 0, 0], // translateをX,Y,Zで指定
},
},
});
スライド数の注意点
本記事で検証を行っているv11では、ループさせる場合の必要最低スライド数に条件があります。
用意するスライド数は、slidesPerView
(1回に表示するスライド枚数) + slidesPerGroup
(一度にスライドさせる枚数)以上でなければいけません。slidesPerView
とslidesPerGroup
の初期値はともに1
です。
たとえば、画面に3枚表示して一度に1枚ずつスライドさせる場合には、4枚以上のスライドが必要です。
スライド数が足りていない場合、コンソールに以下のエラーがでます。スライド数を追加するか、もしくはslidesPerView
やslidesPerGroup
の値を低くするよう促しています。
Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled and not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters
さらに、centeredSlides: true
(アクティブなスライドを中央配置する)を指定する場合は少し注意が必要です。slidesPerView
やslidesPerGroup
の割り付け状況により、必要最低スライド数に加えて、1枚追加のスライドが必要になる場合があります。
そのため、centeredSlides: true
を指定している「カードエフェクトを使用した作例」では、調整を行い4枚のスライドで作成しています。
keen-slider.js
keen-slider.jsはカスタマイズが前提とされているシンプルなカルーセルライブラリです。カルーセルを実装するために必要なコアな機能が用意されていて、Slick.jsやSwiper.js同様にタッチ・スワイプ操作にも対応しています。よくある機能の実装方法については公式ドキュメントで作例が紹介されています。
機能が豊富なJSライブラリは便利なことも多いですが、ウェブサイトの要件次第でライブラリ自体のデフォルト挙動が不都合になる場合があります。このライブラリではコアな役割はライブラリにまかせつつ、必要な機能はライブラリの挙動になるべく干渉せず実装できます。
このJSライブラリの基本的な作例を用意しました。ドットのインジケーターや前後へのスライドボタンなど、必要な機能はイベントやメソッドを利用して実装しています。
基本の作例
<div class="keen-slider carousel">
<div class="keen-slider__slide">
<div class="carousel-item carousel-item__bgcBlue">1</div>
</div>
<div class="keen-slider__slide">
<div class="carousel-item carousel-item__bgcYellow">2</div>
</div>
<div class="keen-slider__slide">
<div class="carousel-item carousel-item__bgcRed">3</div>
</div>
</div>
<button type="button" id="arrow-left" class="arrow arrow--left">
<img src="./assets/arrow-left.svg" alt="">
</button>
<button type="button" id="arrow-right" class="arrow arrow--right">
<img src="./assets/arrow-right.svg" alt="">
</button>
<div id="dots" class="dots"></div>
const keenSlider = new KeenSlider(".keen-slider", {
loop: true,
created: (instance) => { // はじめて初期化された後に実行
// 左の矢印ボタンをクリックしたら1つ前のスライドに移動
document
.getElementById("arrow-left")
.addEventListener("click", () => {
instance.prev();
});
// 右の矢印ボタンをクリックしたら1つ先のスライドに移動
document
.getElementById("arrow-right")
.addEventListener("click", () => {
instance.next();
});
// ドットインジケーターを生成する親要素を取得
const dots_wrapper = document.getElementById("dots");
// スライドと同じ数のドットインジケーターを生成
const slides = document.querySelectorAll(".keen-slider__slide");
slides.forEach((t, idx) => {
const dot = document.createElement("button");
dot.classList.add("dot");
dots_wrapper.appendChild(dot);
// ドットインジケーターをクリックしたら同じ列番号のスライドへ移動
dot.addEventListener("click", () => {
instance.moveToSlide(idx);
});
});
// CSSクラスの更新
updateClasses(instance);
},
slideChanged: (instance) => { // 現在表示されているスライドが変更された時に実行
// CSSクラスの更新
updateClasses(instance);
},
})
/**
* 各要素のCSSクラスを更新
* @param instance
*/
function updateClasses(instance) {
// 現在表示しているスライドの列番号を取得
const slide = instance.details().relativeSlide;
// 生成されたドットインジケーターの要素を取得し状態を更新
const dots = document.querySelectorAll(".dot");
dots.forEach((dot, idx) => {
idx === slide
? dot.classList.add("dot--active")
: dot.classList.remove("dot--active");
})
}
わかりやすいカルーセルを心がけよう
カルーセルは便利なユーザーインターフェイスですが、はじめに表示されているスライド以外はユーザーに気づかれにくいといったデメリットも存在します。
今回紹介したほとんどのサンプルは、次のスライドが存在していることが視覚的にわかりにくいため、ユーザーインターフェイスであることに気づかれない可能性があります。Swiper.jsで紹介したカバーフローのサンプルのように次のスライドを一部表示させるなど、効果的に使うためにはカルーセルの特徴をおさえておく必要があるでしょう。
まとめ
自力でゼロから実装すると大変なカルーセルですが、ライブラリを使用することで手軽に実装できます。基本的な機能はどのライブラリも似ているところがありますが、少し踏み込むとそれぞれの特徴あるので目的に合わせて選びましょう。
紹介したライブラリの中から選ぶ場合は、以下の判断基準を参考にしてみてください。
- 高機能で多彩な表現を使用したい場合はSwiper.js
- jQueryを使用しているプロジェクトや、Swiper.jsほど機能を必要としない場合はSlick.js
- 独自の機能や演出を取り入れたい場合はkeen-slider.js
※この記事が公開されたのは3年前ですが、半年前の4月に内容をメンテナンスしています。