Creating a Responsive Carousel with Tailwind and React (No UI Library!)

01-05-2025

Creating a Responsive Carousel with Tailwind and React (No UI Library!)

Most carousels rely on heavy UI libraries, but if you're using React with Tailwind CSS, you can build a smooth, responsive carousel without adding extra dependencies.

In this post, I’ll show you how to create a clean, functional image carousel with:

  • ✅ Tailwind CSS for layout and responsiveness
  • ✅ React state to control active slide
  • ✅ No external packages (no Swiper, no Splide, no UI kits)

Let’s go 👇


📸 Step 1: Basic Carousel Layout

We start by laying out slides in a horizontally scrollable container.

// Carousel.tsx
"use client";

import { useState } from "react";
import Image from "next/image";

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

export default function Carousel() {
  const [current, setCurrent] = useState(0);

  const next = () => setCurrent((prev) => (prev + 1) % images.length);
  const prev = () => setCurrent((prev) => (prev - 1 + images.length) % images.length);

  return (
    <div className="relative w-full max-w-4xl mx-auto overflow-hidden">
      <div className="flex transition-transform duration-500"
           style={{ transform: `translateX(-${current * 100}%)` }}>
        {images.map((src, index) => (
          <div className="min-w-full" key={index}>
            <Image src={src} alt={`Slide ${index + 1}`} width={1200} height={600} className="object-cover w-full" />
          </div>
        ))}
      </div>

      {/* Arrows */}
      <button onClick={prev} className="absolute left-4 top-1/2 -translate-y-1/2 bg-black/50 text-white px-3 py-1 rounded">
        ‹
      </button>
      <button onClick={next} className="absolute right-4 top-1/2 -translate-y-1/2 bg-black/50 text-white px-3 py-1 rounded">
        ›
      </button>
    </div>
  );
}

🧠 Step 2: Tailwind Styling Notes

  • You don’t need overflow-x-scroll or flex wrapping here — instead:

  • Use min-w-full to force each slide to take 100% width

  • Use flex on the container to lay slides side-by-side

  • Add transform to shift the view based on current index

📱 Step 3: Make It Responsive Tailwind makes responsiveness easy — your slides will automatically adjust to screen size.

To improve UX:

  • Add object-cover to images

  • Use aspect-[16/9] or fixed height for consistency

  • Wrap the carousel in max-w-[90%] for mobile spacing

🔄 Optional: Add Auto Slide

useEffect(() => {
  const interval = setInterval(() => {
    setCurrent((prev) => (prev + 1) % images.length);
  }, 5000);
  return () => clearInterval(interval);
}, []);

Use this if you want the carousel to autoplay every 5 seconds.

🧩 Bonus: Dot Navigation

<div className="flex justify-center gap-2 mt-4">
  {images.map((_, i) => (
    <button
      key={i}
      onClick={() => setCurrent(i)}
      className={`w-3 h-3 rounded-full ${i === current ? "bg-black" : "bg-gray-400"}`}
    />
  ))}
</div>

🏁 Final Thoughts You don’t need a huge UI library for every feature. Building your own carousel gives you:

  • Full control over layout

  • Zero extra bundle size

  • Tailored design with Tailwind

🚀 Need a version with swipe support, touch gestures, or accessibility? Let me know and I’ll cover it in a follow-up post!