0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🧭 はじめに:画像カルーセルの「あるある」と現場の課題

Webサイトやアプリを作っていると、画像スライダーやカルーセルを入れる場面はよくあります。例えば以下のような場面です:

  • トップページのヒーローバナー
  • ECサイトの商品ギャラリー
  • LPのレビューセクション

一見シンプルに見えるこの機能、実装に入ると実は意外と面倒。「自動再生するけどホバーで止めたい」「レスポンシブ対応が大変」「スワイプ対応したい」「再レンダリングで壊れる」など、現場での苦労話が絶えません

今回は、React + Tailwind CSS + TypeScriptで、軽量かつ拡張しやすい画像カルーセルをゼロから作り上げていきます。


🔍 技術スタックと仕組みの概要

使用技術

技術 用途
React UI構築
TypeScript 型安全な実装
Tailwind CSS スタイリング
Framer Motion(任意) アニメーション(拡張編)

機能仕様(今回作るもの)

  • 画像を横スライド表示
  • 自動スライド(インターバル設定可)
  • 左右ボタンで手動切替
  • ホバーで自動再生停止
  • レスポンシブ対応
  • 任意:スワイプ操作(モバイル向け)

💻 実装ステップ:1から組む画像スライダー

まずは、最小構成の画像カルーセルを作っていきます。

① コンポーネント構成

ImageSlider/
├── ImageSlider.tsx
└── images.ts

② デモ用画像リスト images.ts

export const images = [
  "/images/img1.jpg",
  "/images/img2.jpg",
  "/images/img3.jpg",
];

③ メインコンポーネント ImageSlider.tsx

import { useState, useEffect } from "react";
import { images } from "./images";

const ImageSlider = () => {
  const [current, setCurrent] = useState(0);
  const length = images.length;

  useEffect(() => {
    const timer = setInterval(() => {
      setCurrent((prev) => (prev + 1) % length);
    }, 3000);
    return () => clearInterval(timer);
  }, [length]);

  return (
    <div className="relative w-full h-64 overflow-hidden">
      <div className="flex transition-transform duration-700 ease-in-out" style={{ transform: `translateX(-${current * 100}%)` }}>
        {images.map((src, index) => (
          <img
            key={index}
            src={src}
            className="w-full object-cover flex-shrink-0"
            alt={`slide-${index}`}
          />
        ))}
      </div>
      <button
        onClick={() => setCurrent((current - 1 + length) % length)}
        className="absolute left-2 top-1/2 -translate-y-1/2 bg-white/70 p-2 rounded-full"
      ></button>
      <button
        onClick={() => setCurrent((current + 1) % length)}
        className="absolute right-2 top-1/2 -translate-y-1/2 bg-white/70 p-2 rounded-full"
      ></button>
    </div>
  );
};

export default ImageSlider;

💡 実務Tips:よくある落とし穴とその回避法

☠️ 落とし穴1:自動再生が止まらない/二重実行

解決法:useEffectclearIntervalを忘れずに。

☠️ 落とし穴2:画像サイズが揃っていないとレイアウトが崩壊

解決法:object-cover と親要素に overflow-hidden をセット。

☠️ 落とし穴3:スマホでスワイプしても動かない

解決法:react-swipeableなどのライブラリを導入 or touchイベントを自前で実装。


🚀 応用・発展:もっと高度なカルーセルを作りたい人へ

🔁 自動再生に「ホバーで一時停止」機能を追加

onMouseEnter={() => clearInterval(timer)}
onMouseLeave={() => startInterval()}

📱 スワイプ対応:react-swipeableの導入

npm install react-swipeable
import { useSwipeable } from "react-swipeable";

const handlers = useSwipeable({
  onSwipedLeft: () => setCurrent((current + 1) % length),
  onSwipedRight: () => setCurrent((current - 1 + length) % length),
});

✨ アニメーション追加:Framer Motionでぬるっと動かす

<motion.div
  animate={{ x: -current * 100 + "%" }}
  transition={{ duration: 0.5 }}
  className="flex"
>

🧾 まとめ:導入のしやすさと拡張性のバランスが鍵

観点 内容
✅ メリット 軽量、自由度が高い、Tailwindで簡単デザイン
⚠️ デメリット 機能追加には多少のJS力が必要
🌱 今後の応用 動画スライダー、サムネイル付き、API連携による動的画像

🌟 さいごに:あなたも画像カルーセルを作ってみよう!

自作することで理解が深まり、業務での応用力も高まります。この記事をベースに、自社プロダクトに最適なスライダーを育ててみてください!

👉 次回:「通貨換算アプリ(為替API)」

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?