Swiperのスライドが1枚のときは動かさない|2枚以上だけ動かす方法

Swiperのスライドが1枚のときは動かさず、2枚以上のときだけ動かす方法 JavaScript
※この記事には広告を含みます / This article contains advertising.
スポンサーリンク

コーポレートサイトをコーディングするとき、商品や強み、お知らせをスライド形式で見せることがありますよね。デザインカンプに複数のカードが並んでいれば、Swiperでそのまま再現すればよさそうです。

でも、その中身がお知らせ投稿やカスタム投稿など、登録されている件数によって表示が変わるコンテンツだったらどうでしょうか。

公開直後のお知らせは「サイトを公開しました」の1件だけ、ということも珍しくありません。1件しかないのに矢印・ドット・スワイプ操作が残っていると、ユーザーには「何を操作できるのだろう」と見えてしまいます。

駆け出しの頃にこのケースに気づいてからは、デザインを再現するだけでなく、公開後にコンテンツが最少件数になる場面まで確認するようになりました。この記事では、スライドが1枚のときはSwiperを初期化せず、通常のカードとして表示する方法をご紹介します。

メモ

この記事でいう「初期化」とは、JavaScriptでSwiperを動かし始め、スワイプ・矢印・ページネーションなどの機能を有効にする処理のことです。

本記事の執筆者:マサトラ

フリーランス歴4年のWebエンジニア。現在は20社以上のWeb制作会社社様と提携し、WordPress構築やLP制作を中心に月3~5件のペースでサイト制作を手がけています。
このブログでは、実務で得た知識やノウハウ、制作現場での気づきを、フリーランスとして活動中の方はもちろん、これからWeb制作を仕事にしたいと考えている方にも役立つよう発信しています。

スポンサーリンク

結論:1枚ならSwiperを初期化しない

お知らせ投稿やカスタム投稿から出力したスライドが1枚だけなら、Swiperの機能そのものが不要です。JavaScriptで枚数を数え、2枚以上のときだけ初期化するのが分かりやすい方法です。

これなら1枚のときは矢印、ページネーション、ドラッグ操作を残さず、カードをそのまま読めます。

デモ:1枚は静的表示、5枚は3枚ずつスライド表示

まずは、件数で表示がどう変わるかを確認してみてください。上は1枚だけなので操作UIがなく、下は5枚のカードをPCでは3枚ずつ並べ、矢印・ドット・スワイプで移動できます。

See the Pen Swiper:1枚と5枚の表示比較 by Sugar (@ms_da_13) on CodePen.

埋め込みが表示されない場合は、CodePenでデモを開くこともできます。

スポンサーリンク

実装手順

ここからはデモの完成形を、土台から順に組み立てます。HTMLでカードと操作UIを置き、CSSで「1枚でも3枚表示時と同じ幅・左寄せ」を作り、最後にJavaScriptで2枚以上だけSwiperを動かします。

手順1:HTMLを通常のカードとして読める形にする

Swiper用のHTMLでも、JavaScriptが動かなかったときに内容を読めるようにしておくと安心です。お知らせ投稿やカスタム投稿を繰り返し出力する処理でswiper-slideを出力し、前後矢印とページネーションは操作用の要素として置きます。

<section class="news-slider">
  <!-- Swiperを初期化しなくても、通常のカードとして読める構造にする -->
  <div class="swiper js-news-swiper">
    <!-- CMSから出力したお知らせを、この中に並べる -->
    <div class="swiper-wrapper">
      <article class="swiper-slide news-card">お知らせ1件目</article>
      <article class="swiper-slide news-card">お知らせ2件目</article>
    </div>

    <!-- 複数件のときだけ使う操作UI。1件時はCSSで隠す -->
    <div class="news-slider__controls">
      <button class="swiper-button-prev" type="button" aria-label="前のお知らせへ"></button>
      <div class="swiper-pagination"></div>
      <button class="swiper-button-next" type="button" aria-label="次のお知らせへ"></button>
    </div>
  </div>
</section>

手順2:1枚を左寄せのカードとして整えるCSSを付ける

1枚でもカードを横幅いっぱいに広げず、3枚表示時と同じ幅のまま左端に置くCSSです。デモの上段と同じ状態になります。

/* 1枚のときだけ付けるis-static。3枚表示と同じカード幅で左寄せにする */
.js-news-swiper.is-static .swiper-wrapper {
  display: flex;
  gap: 16px;
}

.js-news-swiper.is-static .swiper-slide {
  flex: 0 0 calc((100% - 32px) / 3);
  width: calc((100% - 32px) / 3);
}

/* 1枚なら操作する必要がないため、矢印とドットは表示しない */
.js-news-swiper.is-static .news-slider__controls {
  display: none;
}

スマートフォンではカードを横幅いっぱいにしたい場合は、同じセレクタをメディアクエリ内で上書きします。

@media (max-width: 767px) {
  /* スマホでは静的な1枚も横幅いっぱいにする */
  .js-news-swiper.is-static .swiper-slide {
    flex-basis: 100%;
    width: 100%;
  }
}

手順3:2枚以上のときだけJavaScriptでSwiperを動かす

次のコードが今回の主役です。各Swiperの直下にあるスライドだけを数え、1枚ならis-staticを付けて終えます。つまり、1枚のときにはSwiperを初期化しません。

// ページ内にある対象のSwiperを、1つずつ処理する
document.querySelectorAll('.js-news-swiper').forEach((swiperElement) => {
  // 直下の実データのスライドだけを取得する
  const slides = swiperElement.querySelectorAll(
    ':scope > .swiper-wrapper > .swiper-slide'
  );

  // 1枚以下はSwiperを作らず、通常表示用のクラスだけを付けて終える
  if (slides.length < 2) {
    swiperElement.classList.add('is-static');
    return;
  }

  // 2枚以上のときだけ、ここでSwiperを初期化する
  new Swiper(swiperElement, {
    // PCでは最大3枚を横並びにする
    slidesPerView: 3,
    spaceBetween: 16,

    breakpoints: {
      // スマホでは1枚ずつ見せる
      0: { slidesPerView: 1 },
      // 中間幅では2枚を並べる
      768: { slidesPerView: 2 },
      // PCでは最大3枚を並べる
      1024: { slidesPerView: 3 }
    },

    navigation: {
      // このSwiperの中にある「次へ」ボタンだけを紐付ける
      nextEl: swiperElement.querySelector('.swiper-button-next'),
      // このSwiperの中にある「前へ」ボタンだけを紐付ける
      prevEl: swiperElement.querySelector('.swiper-button-prev')
    },
    pagination: {
      // このSwiperの中にあるドットの出力先を指定する
      el: swiperElement.querySelector('.swiper-pagination'),
      // ドットを押して移動できるようにする
      clickable: true
    }
  });
});

is-staticを付けて処理を終えるため、1枚のときにはスワイプや矢印を動かすSwiperの処理そのものが実行されません。今回の主題を実現するために必須なのは、この初期化前の件数判定と手順2のCSSです。

なお、nextElprevElをページ全体から探すのではなく、対象のSwiperの中から探しているのがポイントです。同じページにスライダーが複数あっても、別の矢印を操作してしまうトラブルを避けやすくなります。

手順4:必要なら前後ボタンとドットを整える

Swiperの標準スタイルでは、矢印やドットがカードに重なることがあります。操作UIをカードの下に並べ、ボタンのテキストを出さず矢印だけにする場合は、次を追加します。

/* 操作UIをカードの下へ並べる */
.news-slider__controls {
  display: grid;
  grid-template-columns: 40px 1fr 40px;
  align-items: center;
  gap: 16px;
  margin-top: 16px;
}

/* 標準のabsolute配置を解除し、矢印アイコンだけを表示する */
.news-slider__controls .swiper-button-prev,
.news-slider__controls .swiper-button-next {
  position: static;
  width: 40px;
  height: 40px;
  margin: 0;
  font-size: 0;
}

/* ドットも通常の配置に戻して、カードと重ならないようにする */
.news-slider__controls .swiper-pagination {
  position: static;
  width: auto;
}

お知らせ投稿・カスタム投稿が0件のときは表示方法を決める

ここまでの手順は、お知らせ投稿やカスタム投稿が1件以上あり、HTMLが出力されている場合の見せ方です。サイト公開直後などは、表示したいお知らせ投稿そのものがまだ0件ということもあります。

WordPressではテーマやテンプレートのPHP側で投稿件数を判定し、0件ならお知らせセクション自体を出さないようにできます。空の枠や、使えない矢印・ドットだけをページに残さずに済みます。

ただし、すべてのケースで非表示が正解とは限りません。お知らせ一覧のようにユーザーが内容を期待して訪れる場所なら、「現在、お知らせはありません」とメッセージを出す方法もあります。セクションを隠すかメッセージを出すかは、ページ内でその情報がどれだけ重要か、更新予定があるかで決めましょう。

watchOverflowを使うのはどんなとき?

watchOverflowはSwiperのオプションの1つです。Swiperを動かし始めたあと、表示幅に対してスライドを動かす余地がないときに、操作できない状態へ自動で切り替えるために使います。今回の「1枚ならSwiperを動かさない」判定には不要な、任意の設定です。

たとえば「PCでは3枚表示でスライドが3枚しかないため動かないが、スマホでは1枚ずつ表示するので動かしたい」というケースでは、追加しておくと便利です。

new Swiper('.js-product-swiper', {
  // PCでは3枚を同時に見せる
  slidesPerView: 3,

  // 初期化済みSwiperが動けないときだけロックする任意設定
  watchOverflow: true,

  breakpoints: {
    0: { slidesPerView: 1 },
    1024: { slidesPerView: 3 }
  }
});

1枚ならSwiperを作らない今回の実装と、初期化後のwatchOverflowは別の役割です。まずは件数判定だけで要件を満たし、レスポンシブでの操作制御が必要になったときだけ追加しましょう。

公開前は0件・1件・複数件を確認する

デザインカンプでは複数件の状態しか見えないことが多いですが、お知らせ投稿やカスタム投稿など、登録件数が変わる箇所では少なくとも次の3パターンを確認しておきましょう。

  • 0件: セクションそのものを出さず、空の操作UIを残さない
  • 1件: 通常のカードとして表示し、Swiperを初期化しない
  • 複数件: 矢印、ページネーション、スワイプが正しく動く

さらにslidesPerViewをブレークポイントで変えている場合は、PCとスマートフォンの両方で確認します。2件あってもPCでは2枚とも表示され、スマートフォンではスライドできる、というケースがあるからです。

まとめ

Swiperはデザインを動かすための便利なライブラリですが、実装時には公開後のコンテンツ件数も考えておきたいところです。

1枚のときはSwiperを初期化せず、通常のカードとして表示する。複数件のときだけスライダーとして動かす。このひと手間を入れておくと、公開直後でも不自然なUIを残さずに済みます。

スポンサーリンク