How to add Tailwind CSS Carousel React (no library)
Tags: react, tailwindcss, webdev, tutorial
Published: 2024-04-23 16:21:48

In this tutorial, we will see how to add a Tailwind CSS carousel in React without using any library. 
**See Also**: [How to Use Carousel Slider in Shadcn UI with Next.js](https://frontendshape.com/post/how-to-use-carousel-slider-in-shadcn-ui-with-nextjs)
<br>

### React with Tailwind CSS  Carousel Slider 
Modified carousel section: added **overflow-hidden** class to prevent image overflow, wrapped items in **carousel-inner** div with flex layout, applied **transition-transform** and **duration-500** classes for smooth transitions, calculated transform property to translate items horizontally, added **flex-shrink-0** and w-full classes to prevent shrinking and ensure full width, used **picsum.photos** for dummy images.
```react
import { useState } from "react";

const Carousel = ({ images }) => {
  const [currentIndex, setCurrentIndex] = useState(0);

  const handlePrevClick = () => {
    setCurrentIndex((currentIndex - 1 + images.length) % images.length);
  };

  const handleNextClick = () => {
    setCurrentIndex((currentIndex + 1) % images.length);
  };

  return (
    <div className="relative">
      <div className="carousel overflow-hidden">
        <div
          className="carousel-inner flex transition-transform duration-500"
          style={{ transform: `translateX(-${currentIndex * 100}%)` }}
        >
          {images.map((image, index) => (
            <div key={index} className="carousel-item flex-shrink-0 w-full">
              <img src={image.src} alt={image.alt} className="w-full h-auto" />
            </div>
          ))}
        </div>
      </div>
      <button
        className="absolute left-0 top-1/2 -translate-y-1/2 bg-gray-300 rounded-full p-2 hover:bg-gray-400 transition-colors duration-300"
        onClick={handlePrevClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="h-6 w-6"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M15 19l-7-7 7-7"
          />
        </svg>
      </button>
      <button
        className="absolute right-0 top-1/2 -translate-y-1/2 bg-gray-300 rounded-full p-2 hover:bg-gray-400 transition-colors duration-300"
        onClick={handleNextClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="h-6 w-6"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M9 5l7 7-7 7"
          />
        </svg>
      </button>
    </div>
  );
};

const App = () => {
  const images = [
    { src: "https://picsum.photos/800/400?random=1", alt: "Image 1" },
    { src: "https://picsum.photos/800/400?random=2", alt: "Image 2" },
    { src: "https://picsum.photos/800/400?random=3", alt: "Image 3" },
  ];

  return (
    <div className="container mx-auto">
      <h1 className="text-3xl font-bold mb-4">My Carousel</h1>
      <Carousel images={images} />
    </div>
  );
};

export default App;
```
![react tailwind carousel](https://frontendshape.com/storage/canvas/images/FNvP2AxLIR68CikIOZXQGKtfMXEtRmogfbUxwLYc.png)

### React Carousel Slider (Tailwind CSS) - TypeScript 
```react
import React, { useState } from 'react';

interface Image {
  src: string;
  alt: string;
}

interface CarouselProps {
  images: Image[];
}

const Carousel: React.FC<CarouselProps> = ({ images }) => {
  const [currentIndex, setCurrentIndex] = useState<number>(0);

  const handlePrevClick = () => {
    setCurrentIndex((currentIndex - 1 + images.length) % images.length);
  };

  const handleNextClick = () => {
    setCurrentIndex((currentIndex + 1) % images.length);
  };

  return (
    <div className="relative">
      <div className="carousel overflow-hidden">
        <div
          className="carousel-inner flex transition-transform duration-500"
          style={{ transform: `translateX(-${currentIndex * 100}%)` }}
        >
          {images.map((image, index) => (
            <div key={index} className="carousel-item flex-shrink-0 w-full">
              <img src={image.src} alt={image.alt} className="w-full h-auto" />
            </div>
          ))}
        </div>
      </div>
      <button
        className="absolute left-0 top-1/2 -translate-y-1/2 bg-gray-300 rounded-full p-2 hover:bg-gray-400 transition-colors duration-300"
        onClick={handlePrevClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="h-6 w-6"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M15 19l-7-7 7-7"
          />
        </svg>
      </button>
      <button
        className="absolute right-0 top-1/2 -translate-y-1/2 bg-gray-300 rounded-full p-2 hover:bg-gray-400 transition-colors duration-300"
        onClick={handleNextClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="h-6 w-6"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M9 5l7 7-7 7"
          />
        </svg>
      </button>
    </div>
  );
};

const App: React.FC = () => {
  const images: Image[] = [
    { src: 'https://picsum.photos/800/400?random=1', alt: 'Image 1' },
    { src: 'https://picsum.photos/800/400?random=2', alt: 'Image 2' },
    { src: 'https://picsum.photos/800/400?random=3', alt: 'Image 3' },
  ];

  return (
    <div className="container mx-auto">
      <h1 className="text-3xl font-bold mb-4">My Carousel</h1>
      <Carousel images={images} />
    </div>
  );
};

export default App;
```

### React Tailwind Carousel with Autoplay and Pagination
This carousel has **autoplay**, pagination dots with a **handleDotClick **function to update the currentIndex, and the active dot is highlighted with a different background color.
```react
import { useState, useEffect } from "react";

const Carousel = ({ images, autoplayInterval = 3000 }) => {
  const [currentIndex, setCurrentIndex] = useState(0);

  useEffect(() => {
    const autoplayTimer = setInterval(() => {
      handleNextClick();
    }, autoplayInterval);

    return () => clearInterval(autoplayTimer);
  }, [currentIndex, autoplayInterval]);

  const handlePrevClick = () => {
    setCurrentIndex((currentIndex - 1 + images.length) % images.length);
  };

  const handleNextClick = () => {
    setCurrentIndex((currentIndex + 1) % images.length);
  };

  const handleDotClick = (index) => {
    setCurrentIndex(index);
  };

  return (
    <div className="relative">
      <div className="carousel overflow-hidden">
        <div
          className="carousel-inner flex transition-transform duration-500"
          style={{ transform: `translateX(-${currentIndex * 100}%)` }}
        >
          {images.map((image, index) => (
            <div key={index} className="carousel-item flex-shrink-0 w-full">
              <img src={image.src} alt={image.alt} className="w-full h-auto" />
            </div>
          ))}
        </div>
      </div>
      <button
        className="absolute left-0 top-1/2 -translate-y-1/2 bg-gray-300 rounded-full p-2 hover:bg-gray-400 transition-colors duration-300"
        onClick={handlePrevClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="h-6 w-6"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M15 19l-7-7 7-7"
          />
        </svg>
      </button>
      <button
        className="absolute right-0 top-1/2 -translate-y-1/2 bg-gray-300 rounded-full p-2 hover:bg-gray-400 transition-colors duration-300"
        onClick={handleNextClick}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="h-6 w-6"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M9 5l7 7-7 7"
          />
        </svg>
      </button>
      <div className="carousel-dots flex justify-center mt-4">
        {images.map((_, index) => (
          <button
            key={index}
            className={`carousel-dot mx-1 w-3 h-3 rounded-full ${index === currentIndex ? "bg-gray-800" : "bg-gray-400"
              }`}
            onClick={() => handleDotClick(index)}
          />
        ))}
      </div>
    </div>
  );
};

const App = () => {
  const images = [
    { src: "https://picsum.photos/800/400?random=1", alt: "Image 1" },
    { src: "https://picsum.photos/800/400?random=2", alt: "Image 2" },
    { src: "https://picsum.photos/800/400?random=3", alt: "Image 3" },
  ];

  return (
    <div className="container mx-auto">
      <h1 className="text-3xl font-bold mb-4">
        {" "}
        Carousel Autoplay and Pagination
      </h1>
      <Carousel images={images} autoplayInterval={5000} />
    </div>
  );
};

export default App;
```
![react tailwind carousel autoplay and pagination](https://frontendshape.com/storage/canvas/images/PFXScuIJHpDLgLdFWXt9zZgzVcqFF5yQviD3efOQ.png)

## See Also
&#x1F449;[React with Tailwind CSS File Upload Example](https://frontendshape.com/post/react-with-tailwind-css-file-upload-example)
&#x1F449;[How to Use Toastify in React with Tailwind CSS](https://frontendshape.com/post/how-to-use-toastify-in-react-with-tailwind-css)
&#x1F449;[Create a Responsive Navbar React Tailwind CSS TypeScript](https://frontendshape.com/post/create-a-responsive-navbar-react-tailwind-css-and-typescript)
&#x1F449;[React TypeScript Tailwind CSS Popup Modal Tutorial](https://frontendshape.com/post/react-typescript-tailwind-css-popup-modal-tutorial)
&#x1F449;[How to Add Drag-and-Drop Image Upload with Dropzone in React Using Tailwind CSS](https://frontendshape.com/post/how-to-add-drag-and-drop-image-upload-with-dropzone-in-react-using-tailwind-css)