画面幅内に任意の枚数を表示させるSwiperスライダーを実装してみる(備忘録)

今回は画面幅内に任意の枚数を表示させるSwiperスライダーを実装していく。

また、アクティブになっていない画像は、透過されていたりグレーアウトされていることが多いので、今回は透過して対応するようにした。

ただ透過するだけでもいいのだが、もう少し実務に近づけたかたちにしたかったので、非アクティブの画像は縮小して表示させるように対応した。

なお、前回の記事のソースをもとに対応していくので、まだご覧になっていない方は一度読んでからだと理解が深まるかと思う。

前回の記事はこちら

HTMLの記述について

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="../reset.css">
  <link rel="stylesheet" href="https://unpkg.com/swiper@8/swiper-bundle.min.css" />
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main>
    <div class="swiperCont">
      <div class="swiper mySwiper">
        <div class="swiper-wrapper">
          <div class="swiper-slide">
            <img src="img1.jpg" />
          </div>
          <div class="swiper-slide">
            <img src="img2.jpg" />
          </div>
          <div class="swiper-slide">
            <img src="img3.jpg" />
          </div>
          <div class="swiper-slide">
            <img src="img4.jpg" />
          </div>
        </div>
      </div>
      <div class="swiper-pagination"></div>
      <div class="swiper-button-prev"></div>
      <div class="swiper-button-next"></div>
    </div>
    <section>
      <div class="ly_inner" id="menu1">
        <h2>menu1</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu2">
        <h2>menu2</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu3">
        <h2>menu3</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu4">
        <h2>menu4</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="menu5">
        <h2>menu5</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
  </main>
  <script src="https://unpkg.com/swiper@8/swiper-bundle.min.js"></script>
  <script src="style.js"></script>
</body>
</html>

前回の記事と同様のため、解説は省略する。

CSSの記述について

@charset "utf-8";

/* ==========================
  初期設定
========================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}
body {
  position: relative;
}
img {
  width: 100%;
}

/* ==========================
  swiperslider
========================== */
.swiperCont {
  width: 80%;
  margin: 0 auto;
  position: relative;
}
.swiper {
  width: 100%;
}
.swiper-button-next,
.swiper-rtl .swiper-button-prev,
.swiper-button-prev,
.swiper-rtl .swiper-button-next {
  background-color: #ccc;
  border-radius: 50%;
  padding: 25px;
}
.swiper-button-next,
.swiper-rtl .swiper-button-prev {
  right: -70px;
}
.swiper-button-prev,
.swiper-rtl .swiper-button-next {
  left: -70px;
}
.swiper-button-next:focus,
.swiper-rtl .swiper-button-prev:focus,
.swiper-button-prev:focus,
.swiper-rtl .swiper-button-next:focus {
  outline: none;
}
.swiper-button-prev:after,
.swiper-rtl .swiper-button-next:after,
.swiper-button-next:after,
.swiper-rtl .swiper-button-prev:after {
  color: #fff;
  font-size: 18px;
}
.swiper-pagination-bullet-active {
  opacity: var(--swiper-pagination-bullet-opacity, 1);
  background: #444;
}
.swiper-horizontal > .swiper-pagination-bullets,
.swiper-pagination-bullets.swiper-pagination-horizontal,
.swiper-pagination-custom,
.swiper-pagination-fraction {
  bottom: -30px;
}
.swiper-backface-hidden .swiper-slide {
  transition: .3s;
}
.swiper-backface-hidden .swiper-slide.swiper-slide-prev,
.swiper-backface-hidden .swiper-slide.swiper-slide-next {
  opacity: .3;
  transform: scale(.8);
}

@media screen and (max-width: 767px) {
  .swiperCont {
    width: 100%;
    padding: 0 70px;
  }
  .swiper-button-next,
  .swiper-rtl .swiper-button-prev {
    right: 10px;
  }
  .swiper-button-prev,
  .swiper-rtl .swiper-button-next {
    left: 10px;
  }
  .swiper-button-next,
  .swiper-rtl .swiper-button-prev,
  .swiper-button-prev,
  .swiper-rtl .swiper-button-next {
    padding: 24px;
  }
  .swiper-button-prev:after,
  .swiper-rtl .swiper-button-next:after,
  .swiper-button-next:after,
  .swiper-rtl .swiper-button-prev:after {
    font-size: 16px;
  }
}

/* ==========================
  コンテンツの中身
========================== */
.ly_inner {
  width: 100%;
  max-width: 1080px;
  margin: 100px auto;
  padding: 20px;
  background-color: #ccc;
}
.ly_inner h2 {
  font-size: 150%;
  font-weight: bold;
  margin-bottom: 30px;
}
.md_textblock > * + * {
  margin-top: 10px;
}

CSSでは、画面内に画像が増える関係でナビゲーション(画像両端の矢印)の大きさを小さくしている。このことについては、前回の記事でも触れているので、解説は省略させていただく。

今回解説するのは、下記のソースになる。

.swiper-backface-hidden .swiper-slide {
  transition: .3s;
}
.swiper-backface-hidden .swiper-slide.swiper-slide-prev,
.swiper-backface-hidden .swiper-slide.swiper-slide-next {
  opacity: .3;
  transform: scale(.8);
}

Swiperスライダーを実装したときに、現在表示されている画像(テキストエリアの場合もあり)に対しては、swiper-slide-activeというクラスが付与される。

また、swiper-slide-activeの手前の画像にはswiper-slide-prev、swiper-slide-activeの直後の画像にはswiper-slide-nextというクラスが付与される。

今回はこれを利用して、CSSを記述していくことになる。

transitionをつけているのは、スライダーが切り替わるときにカクカクしたり、すぐに切り替わったりするような挙動にならないためにつけている。

非アクティブのswiper-slide-prev、swiper-slide-nextに対しては、opacityで任意の透過させたい値を入れ、transformのscaleでどのくらい縮小させたいかの値を入れている。

これでCSSの対応は完了となる。

例えばページ上で、「ナビゲーション(画像両端の矢印)ありのスライダー部分」の2枚目が表示されているようなとき、「インジケーター部分を画像にしたサムネイル部分」の2枚目が連動して表示されるように見せるための設定をしている。

JavaScriptの記述について

'use strict'

// swiperslider
const swiper = new Swiper('.mySwiper', {
  spaceBetween: 10,
  slidesPerView: 1.5,
  breakpoints: {
    768: {
      slidesPerView: 3,
      spaceBetween: 15,
    },
  },
  centeredSlides: true,
  loop: true,
  pagination: {
    el: '.swiper-pagination',
    clickable: true,
  },
  navigation: {
    nextEl: '.swiper-button-next',
    prevEl: '.swiper-button-prev',
  },
})

コード量も少ないので、変わった部分だけに注目して解説していきたい。

spaceBetweenについて

spaceBetweenに任意の値を入れることによって、スライド間の余白(マージン)を調整することができる。下記の公式ドキュメントにも解説されているので参考にしてみるといいかと思う。

Swiper API

slidesPerViewについて

slidesPerViewに任意の整数値を入れると、指定した画面幅内に入れた数値分の画像(テキストエリアの場合もあり)が表示されるようになる。

また、小数点で数値を入れた場合、指定した画面幅内で少し見切れたかたちで画像が表示されるようになる。こっちの方がよく完成されたページではみることが多いのではないかと思う。

Swiper API

breakpointsについて

breakpointsについては、下記の公式ドキュメントをご覧いただいた方が解説がしやすいので、こちらをもとに解説していきたい。

Swiper API

①について

ここにはデフォルトの値を入れるのだが、一番狭い幅をデフォルト値で当てはめるようにする。

②について

指定した数値の幅以上の場合、spaceBetweenやslidesPerViewの値を入れることで、その画面幅以上になった時にページ上に反映されるようになる。

centeredSlidesについて

centeredSlidesをtrueにすることで、これまでは一番左側がスライダーの一番最初として認識されていた画像(テキストエリアの場合もあり)が、真ん中に表示されている画像が1番最初の画像として認識されるようになる。公式ドキュメントは下記に貼っておく。

Swiper API

以上で実装完了だ。

1 返信

コメントはクローズされています。