swiper は jQuery でしか実装したことはありませんでしたが
React および Next.js で実装してみたので記録いたします。
📌 使用ツール
- Next.js / React / TypeScript
- Swiper v11
- Sass (CSS Modules)
📌 導入手順
(参考)
① 依存パッケージ導入
# npm
npm i swiper sass
# yarn
yarn add swiper sass
# pnpm
pnpm add swiper sass
② ディレクトリ構成(参考例)
src/
└─ app/
├─ components/
│ └─ atoms/
│ └─ swiper/
│ ├─ CustomSwiper.tsx
│ └─ CustomSwiper.module.scss
├─ page.tsx
└─ globals.css # Tailwindや全体CSSがあれば
③ コンポーネント & スタイル作成
-
use clientを忘れずに! -
swiperの詳細項目は、最後の記載しております
CustomSwiper.tsx
"use client";
import "swiper/css";
import { Swiper, SwiperSlide } from "swiper/react";
import styles from "./CustomSwiper.module.scss";
export default function CustomSwiper() {
return (
<Swiper
slidesPerView="auto" // 表示するスライドの数を自動で調整。
spaceBetween={20} // 各スライド間の余白(間隔)をピクセル単位で指定
loop // 無限ループモード。最後→最初になるように循環。
centeredSlides // 現在アクティブなスライドを中央寄せに配置。
observer // SwiperがDOM変化を自動で検知するようにする
observeParents // 親要素のサイズや表示状態が変更時も自動的に更新する
loopPreventsSliding={false} // true(=ループの端で一瞬止まる挙動)
onInit={(sw) => sw.update()} // 再読み込み
onResize={(sw) => sw.update()} // 再読み込み
// BDにも対応(例)
// slidesOffsetBefore:スライダーの左端に余白を追加。
// slidesOffsetAfter:スライダーの右端に余白を追加。
breakpoints={{
0: { slidesOffsetBefore: 20, slidesOffsetAfter: 20 },
340: { slidesOffsetBefore: 0, slidesOffsetAfter: 0 },
}}
>
{/* ダミー6枚:ループ安定用(最低6枚あると安定しやすい) */}
{[1, 2, 3, 4, 5, 6].map((n) => (
<SwiperSlide key={n} className={styles.slide}>
<div>{n}</div>
</SwiperSlide>
))}
</Swiper>
);
}
Swiper.module.scss
/* スライドのcss(お好みで指定) */
.slide {
background-color: #d7cdbe;
width: 300px;
height: 300px;
/* slidesPerView:"auto" のとき必須:固定幅にする(仮で300px)*/
flex: 0 0 300px;
display: flex;
justify-content: center;
align-items: center;
}
/* レスポンシブ対応時に追記 */
@media (min-width: 768px) {
.slide {
max-width: 280px;
flex-basis: 280px;
}
}
④ オプションの追加 / モジュール導入
- Swiper v9以降では、必要な機能だけを「モジュール」として読み込む仕組みになっています
- 使用する機能に応じて、
swiper/modulesからインポートし、modules={[...]}に指定する必要があります - 例として下記2点を詳細、その他はオプション一覧を参照ください
例:ページネーション追加
// 追加
import { Pagination } from "swiper/modules";
import "swiper/css/pagination";
// <Swiper ...> に追記
modules={[Pagination]} // ← ドットUI(ページネーション)を有効化
pagination={{ clickable: true }} // ← ドットをクリックでスライド移動
例:自動再生追加
// 追加
import { Autoplay } from "swiper/modules";
// <Swiper ...> に追記
modules={[Autoplay]} // ← 自動再生モジュールを有効化
autoplay={{
delay: 3000, // スライドの切り替え間隔(ミリ秒)→ 3000ms = 3秒ごとに切り替え
disableOnInteraction: true, // ユーザーが操作(スワイプやクリック)したら自動再生を停止
// false にすると操作後も再開する
pauseOnMouseEnter: true, // PCでマウスをスライド上に乗せたときに一時停止(UX向上)
}}
💡 複数のモジュールを使う場合
- 配列でまとめて指定できます。
例:modules={[Pagination, Autoplay]}
コード例
"use client";
import "swiper/css";
import "swiper/css/pagination";
import { Swiper, SwiperSlide } from "swiper/react";
import { Pagination, Autoplay } from "swiper/modules";
import styles from "./CustomSwiper.module.scss";
export default function CustomSwiperFull() {
return (
<Swiper
slidesPerView="auto"
spaceBetween={20}
loop
centeredSlides
observer
observeParents
loopPreventsSliding={false}
onInit={(sw) => sw.update()}
onResize={(sw) => sw.update()}
breakpoints={{
0: { slidesOffsetBefore: 20, slidesOffsetAfter: 20 },
340: { slidesOffsetBefore: 0, slidesOffsetAfter: 0 },
}}
modules={[Pagination, Autoplay]} // ← まとめて指定
pagination={{ clickable: true }} // ← ドットナビ
autoplay={{ delay: 3000, disableOnInteraction: true }} // ← 自動再生
>
{[1, 2, 3, 4, 5, 6].map((n) => (
<SwiperSlide key={n} className={styles.slide}>
<div>{n}</div>
</SwiperSlide>
))}
</Swiper>
);
}
📌 Swiper オプション早見表(モジュール要否つき)
| 分類 | オプション名 | 型・値 | 主な役割 | モジュール要否 | よく使う設定例 | 挙動 |
|---|---|---|---|---|---|---|
| レイアウト | slidesPerView |
"auto" / 数値 |
同時表示枚数 | 不要 |
"auto" / 3
|
"auto"なら子要素のCSS幅に追従。3なら常に3枚を等幅で表示。 |
spaceBetween |
数値(px) | スライドの間隔 | 不要 | 20 |
各スライド間に指定pxの余白。slidesPerView:"auto"と相性◎。 |
|
centeredSlides |
boolean | アクティブを中央配置 | 不要 | true |
中央にフォーカスが来る“カルーセル感”。peek表現に便利。 | |
slidesOffsetBefore/After |
数値(px) | スライダー外側の左右マージン | 不要 |
16 など |
ビューポート両端に余白を足し、端の切れを演出。 | |
breakpoints |
オブジェクト | 画面幅ごとに設定切替 | 不要 | {768:{slidesPerView:3}} |
>=768pxで3枚表示、未満はautoなどレスポンシブ制御。 |
|
| ループ・挙動 | loop |
boolean | 無限ループ | 不要 | true |
末尾→先頭へ連結して循環。スライド数が少なすぎると無効化される点に注意。 |
loopPreventsSliding |
boolean | 可変幅時の詰まり対策 | 不要 | false |
可変幅 + ループの“引っ掛かり”を回避。falseで強制スライド可。 |
|
speed |
数値(ms) | 切替アニメ時間 | 不要 |
600 / 1000
|
体感スムーズさを調整。長めにすると高級感。 | |
allowTouchMove |
boolean | スワイプ可否 | 不要 | false |
操作を禁止して自動/ボタンのみで制御したい時に。 | |
| 自動再生 | autoplay |
オブジェクト | 自動スライド | 必要(Autoplay) | { delay:3000, disableOnInteraction:true } |
一定間隔で自動送り。disableOnInteraction:falseなら操作後も再開。pauseOnMouseEnter:trueでホバー停止も可。 |
| 再計算・監視 | observer |
boolean | DOM変化の検知 | 不要 | true |
タブ切替/表示切替で幅が変わる場合に自動で再レイアウト。 |
observeParents |
boolean | 親の変化も監視 | 不要 | true |
アコーディオン/タブ内にSwiperがある時に安定。 | |
onInit / onResize |
関数 | 初期化/リサイズ時処理 | 不要 | (sw)=>sw.update() |
動的にスライドを出し入れした後にレイアウトを再計算。 | |
| UI | pagination |
オブジェクト | ドット/分数ナビ | 必要(Pagination) | { el:".swiper-pagination", clickable:true, type:"bullets" } |
ドットをクリックでジャンプ。type:"fraction"で「1/5」表示にも。 |
navigation |
オブジェクト | 前後ボタン | 必要(Navigation) | { prevEl:".prev", nextEl:".next" } |
.prev/.next を押すと前後に移動。ループ併用で無限に送れる。 |
|
keyboard |
boolean/オブジェクト | キーボード操作 | 必要(Keyboard) | { enabled:true, onlyInViewport:true } |
←→キーで移動。ビューポート内のみ有効にもできる。 | |
| イベント | onSlideChange |
関数 | 切替検知 | 不要 | (sw)=>console.log(sw.activeIndex) |
指標やアニメ発火のフックに。 |
onSwiper |
関数 | 初期化時にインスタンス取得 | 不要 | (sw)=>console.log(sw) |
sw.slideNext() 等の直接操作が可能。 |
💡 覚えておきたい「安定構成ベスト5」
| 項目 | 推奨設定 | 理由 |
|---|---|---|
| 表示幅 | slidesPerView:"auto" |
CSSで柔軟に幅管理できる |
| 中央寄せ | centeredSlides |
見た目が整いチラ見せに最適 |
| ループ安定化 | loopPreventsSliding={false} |
可変幅×ループのズレ防止 |
| 再計算 | observer + observeParents + onInit/onResize |
Swiper再描画を確実に |
| 外側余白 | slidesOffsetBefore/After |
チラ見せ幅を自然に調整 |
📌 まとめ
Swiper オプションの理解が難しく、レスポンシブ対応が少し面倒でしたが
なんとか実装できました。
今後はこの構成をベースにすれば、再利用が簡単になりそうです。
React / Next.js 環境でSwiperを使いたい方の参考になれば幸いです。