画像+テキストのスライダーでテキストの高さを揃えたい場合のSwiperスライダーを実装してみる(備忘録)

今回は画像+テキストのスライダーでテキストの高さを揃えたい場合のSwiperスライダーを実装していく。

横に並んだときに、テキストの文字数に応じて高さがバラバラになっていると美しく見えない場合がある。そんな時におすすめの実装だ。

なお、今回はスライダーで対応しているが、スライダー以外でも並んだときの高さを揃えたい時に使えるので、汎用性が高くおすすめの方法だ。

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

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">
            <div class="thumbImage">
              <img src="img1.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトル</h3>
              <p>テキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
            </div>
          </li>
          <li class="swiper-slide">
            <div class="thumbImage">
              <img src="img2.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトルタイトル</h3>
              <p>テキストが入ります</p>
            </div>
          </li>
          <li class="swiper-slide">
            <div class="thumbImage">
              <img src="img3.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトルタイトルタイトル</h3>
              <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
            </div>
          </li>
          <li class="swiper-slide">
            <div class="thumbImage">
              <img src="img4.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトルタイトルタイトルタイトル</h3>
              <p>テキストが入りますテキストが入ります</p>
            </div>
          </li>
          <li class="swiper-slide">
            <div class="thumbImage">
              <img src="img1.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトルタイトルタイトルタイトルタイトルタイトル</h3>
              <p>テキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
            </div>
          </li>
          <li class="swiper-slide">
            <div class="thumbImage">
              <img src="img2.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトル</h3>
              <p>テキストが入ります</p>
            </div>
          </li>
          <li class="swiper-slide">
            <div class="thumbImage">
              <img src="img3.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトルタイトルタイトルタイトル</h3>
              <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
            </div>
          </li>
          <li class="swiper-slide">
            <div class="thumbImage">
              <img src="img4.jpg" alt="">
            </div>
            <div class="thumText">
              <h3>タイトルタイトルタイトル</h3>
              <p>テキストが入りますテキストが入ります</p>
            </div>
          </li>
        </ul>
      </div>
      <div class="swiper-button-prev"></div>
      <div class="swiper-button-next"></div>
    </div>
    <section>
      <div class="ly_inner" id="タイトル1">
        <h2>タイトル1</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="タイトル2">
        <h2>タイトル2</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="タイトル3">
        <h2>タイトル3</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="タイトル4">
        <h2>タイトル4</h2>
        <div class="md_textblock">
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
          <p>テキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入りますテキストが入ります</p>
        </div>
      </div>
    </section>
    <section>
      <div class="ly_inner" id="タイトル5">
        <h2>タイトル5</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>

HTMLはそこまで難しいことはしていない。下記のように、画像、画像下にテキストのエリアを設けている。これらを繰り返しているだけだ。

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

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 {
  background-color: #994141;
  height: auto;
}
.swiper-slide .thumText {
  color: #fff;
  padding: 10px;
}
.swiper-slide .thumText h3 {
  font-size: 16px;
  margin-bottom: 10px;
}
.swiper-slide .thumText p {
  font-size: 12px;
}

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

}

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

CSSもそこまで難しいことはしていない。下記のように色や余白を設定しているだけだ。

.swiper-slide {
  background-color: #994141;
  height: auto;
}
.swiper-slide .thumText {
  color: #fff;
  padding: 10px;
}
.swiper-slide .thumText h3 {
  font-size: 16px;
  margin-bottom: 10px;
}
.swiper-slide .thumText p {
  font-size: 12px;
}

JavaScriptの記述について

'use strict'

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

// 要素の高さ揃える
function matchHeight(targetElement) {
  const targetElements = document.querySelectorAll(targetElement)

  if (targetElements.length > 1) {
    let heightArray = []
    targetElements.forEach((element) => {
      const height = element.clientHeight
      heightArray.push(height)
    })
    const maxHeight = Math.max(...heightArray)

    targetElements.forEach((column) => {
      column.style.height = maxHeight + 'px'
    })
  }
}
window.addEventListener('load', () => {
  matchHeight('.thumText h3', '.thumText p')
})

今回は、要素の高さを揃える部分に限って説明していく。

function matchHeight(targetElement) {
  const targetElements = document.querySelectorAll(targetElement)

  if (targetElements.length > 1) {
    let heightArray = []
    targetElements.forEach((element) => {
      const height = element.clientHeight
      heightArray.push(height)
    })
    const maxHeight = Math.max(...heightArray)

    targetElements.forEach((column) => {
      column.style.height = maxHeight + 'px'
    })
  }
}
window.addEventListener('load', () => {
  matchHeight('.thumText h3', '.thumText p')
})

まずページ内の全ての要素に対しての高さが知りたいので、constで変数targetElementsを定義して取り回しがしやすいようにする。

その後、ページ内の要素数が1より大きい時に空の配列の変数heightArrayを定義する。

続いて、forEachのループ処理で各要素の高さを取得し、先ほど定義したheightArrayの配列へpushする。

ここまでで各要素の高さが分かるようになるので、その中で最大値の高さの要素を取得できるようMath.maxを指定している。

最後にforEachのループ処理で、同じ並びにある高さを最大値の高さに合わせてあげるために、CSSの高さが最大値の高さに置き換わるように対応している。

これで関数が作れたので、あとはページの読み込みが完了した時に、高さを揃えたい要素のクラスを指定して実行してあげればよい。

以上で実装完了だ。