サブスク動画コンテンツなどでよく見かける動画一覧がずらっと横に並んでいるSwiperスライダーを実装してみる(備忘録)

今回はサブスク動画コンテンツなどでよく見かける動画一覧がずらっと横に並んでいるSwiperスライダーを実装していく。

HuluやAmazonプライムなどでよく見かけるものだが、今回はホバーした時に背景で動画が再生されるところまでは実装していない。

PC幅では、該当コンテンツに対してホバーした時にコンテンツの内容が拡大され、隠れていたテキストが画像の下に表示されるように対応している。

スマホ幅では、ページを読み込んだ時点で画像と文字が最初から表示された状態にしている。

なお、サブスク系の動画コンテンツページはバナーの印象が大切になってくるので、本来であればもう少し凝ったバナーを配置したほうがいいのだが、今回はフリー画像をそのまま当てはめている点はご了承いただきたい。

ソース自体は前回の記事をもとに作成している。

前回の記事はこちら

それでは実装に入っていく。

HTMLの記述について

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Swiperスライダー</title>
  <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">
        <ul class="swiper-wrapper">
          <li class="swiper-slide new">
            <a href="">
              <div class="thumbImage">
                <img src="img1.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
              </div>
            </a>
          </li>
          <li class="swiper-slide">
            <a href="">
              <div class="thumbImage">
                <img src="img2.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入ります</p>
              </div>
            </a>
          </li>
          <li class="swiper-slide">
            <a href="">
              <div class="thumbImage">
                <img src="img3.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
              </div>
            </a>
          </li>
          <li class="swiper-slide">
            <a href="">
              <div class="thumbImage">
                <img src="img4.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入りますテキストが入ります</p>
              </div>
            </a>
          </li>
          <li class="swiper-slide">
            <a href="">
              <div class="thumbImage">
                <img src="img1.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
              </div>
            </a>
          </li>
          <li class="swiper-slide">
            <a href="">
              <div class="thumbImage">
                <img src="img2.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入ります</p>
              </div>
            </a>
          </li>
          <li class="swiper-slide">
            <a href="">
              <div class="thumbImage">
                <img src="img3.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
              </div>
            </a>
          </li>
          <li class="swiper-slide">
            <a href="">
              <div class="thumbImage">
                <img src="img4.jpg" alt="">
              </div>
              <div class="thumText">
                <h3>タイトル</h3>
                <p>テキストが入りますテキストが入ります</p>
              </div>
            </a>
          </li>
        </ul>
      </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>

前回の記事との変更点は下記の部分である。

<li class="swiper-slide new">
  <a href="">
    <div class="thumbImage">
      <img src="img1.jpg" alt="">
    </div>
    <div class="thumText">
      <h3>タイトル</h3>
      <p>テキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
    </div>
  </a>
</li>
<li class="swiper-slide">
  <a href="">
    <div class="thumbImage">
      <img src="img2.jpg" alt="">
    </div>
    <div class="thumText">
      <h3>タイトル</h3>
      <p>テキストが入ります</p>
    </div>
  </a>
</li>

1番目のliタグに対してnewのクラスをつけ、NEWのアイコンを表示させるようにしている。

liタグ内のコードは、リンクをつけるためにaタグ、あとは画像とテキストが縦に並ぶようにコードを書いてあげればOK。

今回は8個のコンテンツを作成している。

CSSの記述について

@charset "utf-8";

/* ==========================
  初期設定
========================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  position: relative;
  word-wrap: break-word;
}

img {
  width: 100%;
}

/* ==========================
  swiperslider
========================== */
.swiperCont {
  width: 80%;
  margin: 20px auto;
  position: relative;
}

.swiper {
  width: 100%;
}

.swiper-wrapper {
  padding: 30px 0;
}

.swiper-button-next,
.swiper-rtl .swiper-button-prev,
.swiper-button-prev,
.swiper-rtl .swiper-button-next {
  background-color: #ccc;
  border-radius: 50%;
  padding: 30px;
}

.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: 24px;
}

.swiper-slide.new a {
  position: relative;
}

.swiper-slide a {
  display: block;
  background-color: rgba(34, 34, 34, .7);
}

.swiper-slide.new a::before {
  content: "new";
  display: block;
  color: #fff;
  font-size: 12px;
  position: absolute;
  z-index: 101;
  background-color: #ff0000;
  padding: 5px;
  top: 5px;
  left: 5px;
  border-radius: 10px;
}

.swiper-slide a .thumText {
  color: #fff;
  padding: 10px;
}

.swiper-slide a .thumText h3 {
  font-size: 16px;
  margin-bottom: 10px;
}

.swiper-slide a .thumText p {
  font-size: 12px;
}

@media screen and (min-width: 768px) {
  .swiper {
    overflow: inherit;
  }

  .thumText {
    display: none;
  }

  .swiper-slide a {
    transition: .3s;
  }

  .swiper-slide a:hover {
    transform: scale(1.2);
    position: absolute;
    z-index: 100;
  }

  .swiper-slide a:hover .thumText {
    position: relative;
    z-index: 100;
    display: block;
  }

  .swiper-slide a:hover .thumbImage {
    position: relative;
    z-index: 100;
  }
}

@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;
  }

  .thumText {
    display: block;
  }

}

/* ==========================
  コンテンツの中身
========================== */
.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;
}

前回の記事との主な変更点は下記の部分である。

.swiper-slide.new a {
  position: relative;
}

.swiper-slide a {
  display: block;
  background-color: rgba(34, 34, 34, .7);
}

.swiper-slide.new a::before {
  content: "new";
  display: block;
  color: #fff;
  font-size: 12px;
  position: absolute;
  z-index: 101;
  background-color: #ff0000;
  padding: 5px;
  top: 5px;
  left: 5px;
  border-radius: 10px;
}

@media screen and (min-width: 768px) {
  .swiper {
    overflow: inherit;
  }

  .thumText {
    display: none;
  }

  .swiper-slide a {
    transition: .3s;
  }

  .swiper-slide a:hover {
    transform: scale(1.2);
    position: absolute;
    z-index: 100;
  }

  .swiper-slide a:hover .thumText {
    position: relative;
    z-index: 100;
    display: block;
  }

  .swiper-slide a:hover .thumbImage {
    position: relative;
    z-index: 100;
  }
}

@media screen and (max-width: 767px) {
  .thumText {
    display: block;
  }
}

内容的にはそこまで難しいことはしていない。

PC幅の時だけ、swiperのクラスに対してoverflowを初期値inheritに戻すことで、各リストをホバーした時にswiperの大枠からはみ出て拡大されるように対応している。

またthumTextのクラスに対しては、PCのみホバーする前は非表示に、ホバーしてから表示するように対応している。

もしこれにさらに表現を加えて実装するなら、ホバーした時に動画を背景で流してみるなども面白いかもしれない。興味のある方は試してみるといいだろう。

JavaScriptの記述について

'use strict'

// swiperslider
const swiper = new Swiper('.mySwiper', {
  slidesPerView: 1.5,
  spaceBetween: 5,
  breakpoints: {
    768: {
      slidesPerView: 4.5,
      spaceBetween: 20,
    },
  },
  freeMode: true,
  navigation: {
    nextEl: '.swiper-button-next',
    prevEl: '.swiper-button-prev',
  },
})

JavaScriptについては、前回の記事のソースに対して数字だけ変えただけなので解説は省略する。

以上で実装完了だ。