あれもこれも実はswiperで実装出来る!!実務でめっちゃでてくるswiperのカスタマイズサンプルを紹介

コーポレートサイトやLPのHTMLコーディングにおいて必ずといっていいほどでてくる画像スライダーや・タブ切り替え。
そのほとんどはswiperを使うことで実装可能です。
標準の機能だけでは要件を満たせない場合に必要なswiperの実用的なカスタマイズを紹介します!

スライダーのプラグインについて

スライダーのプラグインはいくつかありますが、私自身は主にswiperを使っています

昔はbx-sliderやslick-sliderを使用していましたが最終的にはswiperに落ち着きました。
swiperはカスタマイズがめちゃくちゃ柔軟に行えるので、これさえ使えればほぼどんなスライダーでも対応出来ると思います。

swiperをCDNで読み込む際の注意点

swiperの公式サイトに記載されているCDNからswiperを読み込んだ場合、常に最新のswiperが読み込まれます。
したがってswiperの元のクラスを上書きする形でカスタマイズしている場合、swiperのバージョンが変わった際にバグが起こる可能性があります。

実際にバージョン7に変わった際にswiperのコンテナのクラス名が変更になったため多くのサイトでバグが発生するという事件もありました。

カスタマイズするのであればサーバーに落とすかバージョンを指定して読み込みましょう。

切り替わりのアニメーションをカスタマイズする

拡大しながら切り替わるswiper

アクティブなスライドが常に拡大し続け、フェードで切り替わるスライダーです
自動再生は5秒間で、2秒かけてフェードで切り替わります。

実装するスライダーのサイト
https://maruyama-urban.co.jp/

ポイントはcssのtransitionのタイミングとswiperの自動再生と切り替わり速度の時間を合わせることです

.swiper-slide img {
  transform: scale(1);
  /*スワイパーの切り替え速度と自動再生の停止時間を合計した秒数に設定する*/
  transition: 7s;
}

.swiper-slide-active img {
  transform: scale(2);
}
const swiper = new Swiper(".swiper", {
  autoplay: {
    delay: 5000,
  },
  on: {
    /*
    初回読み込み時に切り替えの時間が含まれていないため、cssで設定したアニメーションのタイミングがずれる
    したがってspeedで設定した秒数分自動再生が始まる時間を遅らせる
    */
    afterInit: function (swiper) {
      swiper.autoplay.stop();
      setTimeout(function () {
        swiper.autoplay.start();
      }, 2000);
    }
  }
});

次のスライドが横から覆うように切り替わるswiper

次のスライドに切り替わる際に元のスライドに覆いかぶさるように次のスライドが横からスライドしてくるスライダーです。

自動再生は1.5秒で.5秒かけてアニメーションさせます

実装するスライダーのサイト
https://www.belmo.com/

※ややこしくなるので斜めに被さる仕様は無視します

ポイントはfadeモードをonにすることでスライダーが全て重なり合った状態にし、speedを0にすることでfadeの切り替えアニメーションを無効化します。

そして、次のスライドがactive時に横から覆いかぶさるようにcssのアニメーションを記述します

また、切り替わりのタイミングで前のスライドも同時にアニメーションしてしまうため、前のスライドに切り替わり時間分のtransition-delayを指定することで次のスライドのみアニメーションをさせています

.swiper-slide {
  /*fedeアニメーションは必要ないため透過を無しにする*/
  opacity: 1 !important;
}

.swiper-slide .image,
.swiper-slide .image img {
  /*切り替わり中は前のスライドのアニメーションを遅らせる*/
  transition-delay: 0.5s;
}

.swiper-slide .image {
  transform: translateX(-100%);
  overflow: hidden;
}

.swiper-slide .image img {
  transform: translateX(100%);
}

.swiper-slide-active {
  /*アクティブなスライドが一番上に来るように*/
  z-index: 2;
}

.swiper-slide-active .image,
.swiper-slide-active .image img {
  transition-delay: 0s;
  transition-duration: 0.5s;
  transform: translateX(0%);
}
const swiper = new Swiper(".swiper", {
  //fadeを有効にすることでスライダーが全て重なり合った状態になる
  effect: "fade",
  //fadeの切り替えは必要ないのでspeedは0s
  speed: 0,
});

左右に見切れるswiper

左右にアクティブなスライド以外が見切れるスライダーを作るには公式で用意されているオプションを使用することで実装できますが、レスポンシブやカスタマイズ性などを考えると下記のoverflowを解除する方法がおすすめです

公式のオプションを使用する方法

https://swiperjs.com/demos#centered

slidesPerViewとcenteredSlidesを使用することでカスタマイズ無しに左右に見切れるスライダーを作ることが可能です

また、左寄せのまま右側だけを見切らせたい場合はslidesPerViewに小数点(2.5等)を指定することで可能です

overflowを解除する方法

実装するスライダーのサイト
https://cxclip.karte.io/

overflowを解除する方法は画面幅によって見切れるスライドの数を変えたい場合に有効な手法です。

ポイントは元々swiperについているoverflow:hidden;を解除しアクティブなスライドを見えるようにし、親要素でoverflow:hidden;を設定します。

.myswiper-wrapper {
  /*ウィンドウ幅からはみ出さないようにする*/
  overflow: hidden;
}

.swiper {
  max-width: 640px;
  /*アクティブなスライド以外も見えるように*/
  overflow: visible !important;
}

その際に重要なのはloopAdditionalSlidesのオプションで見切れるスワイパー用に複製するスライドを追加することです

const swiper = new Swiper(".swiper", {
  //本来見えていない部分にスライドを複製する
  loopAdditionalSlides: 5
});

見切れた部分になんらかの装飾を加えたswiper

上記の左右に見切れたスライダーの場合、アクティブなスライド以外になんらかの装飾を加えることが多いのでいくつか紹介します

見切れた部分を透過させたswiper

.swiper-slideにopacityを設定し、active時のみ透過を無しにすることで可能です

.swiper-slide img {
  transition: 0.3s;
  opacity: 0.2;
}
.swiper-slide-active img {
  opacity: 1;
}

transformを使ってアクティブなスライドだけ拡大させたswiper

.swiper-slideと.swiper-slide-activeにtransform:scale;を適用させました

.swiper-slide {
  transition: 0.3s;
  transform: scale(0.7);
}
.swiper-slide-active {
  transform: scale(1);
}

スライドの隙間を一定に保ったままアクティブなスライドの横幅が大きくなるswiper

これについては私自身も先日非常に悩みました。
元々はslidesPerViewをautoに設定していて、activeなスライドのみwidthを設定し幅を大きくするという方法で進めていたのですがこの方法だと画面幅を変更したときや次のスライドに移動した際に座標がずれるというバグが発生していました。

結局はslidesPerViewを1にしoverflowを解除する方法で.swiper-slide-activeのクラスにwidthを直接指定することで実装することができました

基本的にはswiperの元々のクラスをimportantなどで上書きをするとバグが発生しやすくなるので注意しましょう!

実装するスライダーのサイト
https://logosland.jp/

.swiper {
  /*幅を大きくする分swiperが中央揃えじゃなくなるので位置を調整する*/
  transform: translateX(-50%);
}
.swiper-slide {
  transition: 0.3s ease !important;
}

.swiper-slide-active {
  width: 200% !important;
}

1ページに複数同じ構成のスライダーが存在するときのNavigationとPaginationについて

1ページに複数同じ構成のスライダーが存在する場合はswiperを初期化するJavaScriptの記述もまとめたいですよね。
またWordPressなどのCMSで動的に吐き出される場合は必然的に同じJavaScriptの記述を使用することになります。

.swiperの中にNavigationとPaginationが入っている場合はそのままで問題なし

NavigationとPaginationをクリックしてもそれぞれのスライダーが独立して動きます

const swiper = new Swiper(".swiper", {
  pagination: {
    el: ".swiper-pagination"
  },
  navigation: {
    nextEl: ".swiper-button-next",
    prevEl: ".swiper-button-prev"
  }
});

NavigationとPaginationを.swiperの外に出したい場合

デザイン上、NavigationとPaginationはスライダーの外側に配置したい場合がありますが、.swiperにはoverflow:hidden;が当たっているので、.swiperの外側にNavigationとPaginationの要素を配置する必要があります。

この場合、上記のように同じswiperの初期化だとそれぞれのswiperが連動して動いてしまうためそれぞれ個別にswiperを初期化する必要があります。

$(".myswiper-wrapper").each(function (index, el) {
  const swiper = new Swiper(el.querySelector(".swiper"), {
    pagination: {
      el: el.querySelector(".swiper-pagination")
    },
    navigation: {
      nextEl: el.querySelector(".swiper-button-next"),
      prevEl: el.querySelector(".swiper-button-prev")
    }
  });
});

常に一定のスピードで動くswiper

実装するスライダーのサイト
https://autok.co.jp/

常に一定のスピードで再生されるswiperは自動再生の時間を0秒にすることで可能です

ポイントは.swiper-wrapperに設定されているtransition-timing-functionをlinearにすることです

.swiper-wrapper {
  /*デフォルトのイージングを上書き*/
  transition-timing-function: linear !important;
}
const swiper = new Swiper(".swiper", {
  //自動再生で次のスライドへ切り替わる時間をなくす
  autoplay: {
    delay: 0
  },
});

タブ切り替えでも使えるswiper

スライダーのプラグインはfadeエフェクトを使用することでタブ切り替えの実装でもよく使用されます。

タブ切り替えについては上記のタブを作ります。

基本的にはswiperをフェード切り替えにして、ドラッグでタブを切り替えないようにするだけで大丈夫です。

const swiper = new Swiper(".swiper", {
  effect: "fade",
  fadeEffect: {
    crossFade: true
  },
  //基本的にtabの場合はドラッグで切り替えは必要ない
  allowTouchMove: false,
});

ただこれだけだと、要件を満たさないことが多いのでよくある以下のような機能を実装していきます

  • タブの切り替えボタンを実装
  • タブごとに違った内容が入るので高さが可変する
  • タブの中身が動的に変わる
  • 2つ目のタブに直接遷移する場合がある

独自でタブを切り替えられるボタンを実装する

独自でタブを切り替えるボタンを実装する場合はswiper.slideTo()というメソッドを使用します

特にポイントはないですが、swiperの場合スライドは「0」から始まることに注意しましょう

<div class="tabbtn">
    <button>タブ1</button>
    <button>タブ2</button>
    <button>タブ3</button>
  </div>
$(".tabbtn button").click(function () {
  swiper.slideTo($(this).index());
});

タブのそれぞれの高さが違う場合

タブのそれぞれの高さが違う場合はタブの下に余計な余白がでてしまうため、切り替え時にswiperの高さを再計算する必要があります

autoHeight: trueを設定することでswiper切り替え時に自動で高さを再計算してくれます

const swiper = new Swiper(".swiper", {
  autoHeight: true
});

タブの中身がアコーディオンなどで高さが可変する場合

タブの中身がアコーディオンなどで可変した場合はswiperの高さを再計算する必要があります。

swiper.updateAutoHeight(200)というメソッドを使用することで可能です

$(".js-accordion").click(function () {
  $(".js-accordionTarget")
    .stop()
    .slideToggle(100, function () {
      swiper.updateAutoHeight(200);
    });
});

しかし、これだけだとアコーディオンで開閉するアニメーションとswiperの高さを再計算するアニメーションを同期させることができないので完璧ではありません

サンプルではアニメーションを早くしてごまかしていますが、もっと他にいい方法があれば教えてください汗

別ページから2つ目のタブに遷移する方法

別ページから2つ目のタブが開いた状態で遷移をする場合はinitialSlideのオプションを使用します

URLにパラメーターをつけて、jsで取得、swiperの初期化時にinitialSlideに設定します
こちらも同様にsiwperのスライドは「0」から始まることには注意しましょう

let initialSlideNum = 0;
if (getParam("initialSlideNum")) {
  initialSlideNum = getParam("initialSlideNum");
}
const swiper = new Swiper(".swiper", {
  //1つ目のタブ以外を最初から開いておきたい場合はパラメーターから値を取得
  initialSlide: initialSlideNum,
});

/**
 * Get the URL parameter value
 *
 * @param  name {string} パラメータのキー文字列
 * @return  url {url} 対象のURL文字列(任意)
 */
function getParam(name, url) {
  if (!url) url = window.location.href;
  name = name.replace(/[\[\]]/g, "\\$&");
  var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
    results = regex.exec(url);
  if (!results) return null;
  if (!results[2]) return "";
  return decodeURIComponent(results[2].replace(/\+/g, " "));
}

パラメーターの取得方法については以下記事を引用させていただきました
https://www-creators.com/archives/4463

このスライダーどうやって実装する?

クライアントからの要望で複雑な仕様のスライダーを実装する必要が有る場合は、まず参考サイトをもらいましょう。
他の人ができているということは多分自分でもできるはず!!
そう思って今までやってきました。

ただcanvasタグを使用されている場合は簡単には真似できないので素直にできませんと伝えましょう笑

このスライダーどうやって実装する?といった質問などあれば下記からお気軽にご質問ください!!

ブログ一覧へ