1. HOME
  2. JavaScript
  3. Swiper × window.matchMedia でレスポンシブなスライダー制御を実現する方法
JavaScript - 2025-08-13

Swiper × window.matchMedia でレスポンシブなスライダー制御を実現する方法

Webサイトでスライダー(カルーセル)を実装する際、「スマホではスライダーを表示したいが、PCでは静的なレイアウトにしたい」といったニーズはよくあります。今回は、Swiperと window.matchMedia を組み合わせて、画面サイズに応じて動的にSwiperの有効・無効を切り替える方法を段階的に解説します。

実装のゴール

画面幅表示レイアウトSwiperの動作
768px未満スライダー表示(Swiper有効)有効
768px以上横並びの静的レイアウト無効

1. 基本の構成:Swiperを画面幅で切り替える

まずは、スマホでSwiperを有効化し、PCでは破棄する基本の実装です。

HTML(Swiperの構造)

<div class="swiper-container js-my-swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">スライド1</div>
    <div class="swiper-slide">スライド2</div>
    <div class="swiper-slide">スライド3</div>
  </div>
</div>

JavaScript

let mySwiper = null;
const mediaQuery = window.matchMedia('(max-width: 767px)');

function initSwiper() {
  if (!mySwiper) {
    mySwiper = new Swiper('.js-my-swiper', {
      slidesPerView: 1,
      spaceBetween: 10,
      loop: true,
    });
  }
}

function destroySwiper() {
  if (mySwiper) {
    mySwiper.destroy(true, true);
    mySwiper = null;
  }
}

function handleBreakpoint(e) {
  if (e.matches) 
    initSwiper();
  } else {
    destroySwiper();
  }
}

handleBreakpoint(mediaQuery);
mediaQuery.addEventListener('change', handleBreakpoint);

2. PCでは静的レイアウトに切り替える

Swiperだけでなく、PCでは静的な横並びのブロックにレイアウトを切り替える例です。

HTML(Swiperと静的レイアウトを両方用意)

<!-- スライダー:スマホ用 -->
<div class="swiper-container js-my-swiper" data-role="slider">
  <div class="swiper-wrapper">
    <div class="swiper-slide">アイテム1</div>
    <div class="swiper-slide">アイテム2</div>
    <div class="swiper-slide">アイテム3</div>
  </div>
</div>

<!-- 静的レイアウト:PC用 -->
<div class="static-layout" data-role="static">
  <div class="item">アイテム1</div>
  <div class="item">アイテム2</div>
  <div class="item">アイテム3</div>
</div>

CSS(表示の切り替え)

[data-role="slider"],
[data-role="static"] {
  display: none;
}

@media (max-width: 767px) {
  [data-role="slider"] {
    display: block;
  }
}

@media (min-width: 768px) {
  [data-role="static"] {
    display: flex;
    gap: 16px;
  }

  .static-layout .item {
    flex: 1;
    background: #eee;
    padding: 16px;
    text-align: center;
  }
}

3. HTMLを共通化してJSで動的に切り替える

HTML構造をSwiper用と静的レイアウト用に分けると、同じデータを重複して書くことになるというデメリットがあります。これを避けるために、共通のアイテムリストから、JSでSwiper構造/静的構造に変換する方法を紹介します。

HTML(共通のリストのみ)

<div id="item-container">
  <div class="item">アイテム1</div>
  <div class="item">アイテム2</div>
  <div class="item">アイテム3</div>
</div>

CSS(共通アイテムと静的レイアウト用)

.item {
  background: #eee;
  padding: 16px;
  text-align: center;
}

.static-layout {
  display: flex;
  gap: 16px;
}

.swiper-container {
  width: 100%;
}

JavaScript(DOM変換とSwiper初期化)

let mySwiper = null;
const container = document.getElementById('item-container');
const mediaQuery = window.matchMedia('(max-width: 767px)');
let currentLayout = null;

function setupSwiperLayout() {
  if (currentLayout === 'swiper') return;

  const wrapper = document.createElement('div');
  wrapper.classList.add('swiper-wrapper');

  [...container.children].forEach((item) => {
    const slide = document.createElement('div');
    slide.classList.add('swiper-slide');
    slide.appendChild(item);
    wrapper.appendChild(slide);
  });

  container.innerHTML = '';
  const swiperEl = document.createElement('div');
  swiperEl.classList.add('swiper-container');
  swiperEl.appendChild(wrapper);
  container.appendChild(swiperEl);

  mySwiper = new Swiper('.swiper-container', {
    slidesPerView: 1.2,
    spaceBetween: 10,
    loop: true,
  });

  currentLayout = 'swiper';
}

function setupStaticLayout() {
  if (currentLayout === 'static') return;

  if (mySwiper) {
    mySwiper.destroy(true, true);
    mySwiper = null;
  }

  const items = [];
  container.querySelectorAll('.swiper-slide .item').forEach((item) => {
    items.push(item);
  });

  container.innerHTML = '';
  const staticLayout = document.createElement('div');
  staticLayout.classList.add('static-layout');
  items.forEach((item) => staticLayout.appendChild(item));
  container.appendChild(staticLayout);

  currentLayout = 'static';
}

function handleResize(e) {
  if (e.matches) {
    setupSwiperLayout();
  } else {
    setupStaticLayout();
  }
}

handleResize(mediaQuery);
mediaQuery.addEventListener('change', handleResize);