A React Ref Adventure: Creating a smooth scrolling carousel using React and Tailwind CSS

A React Ref Adventure: Creating a smooth scrolling carousel using React and Tailwind CSS

ยท

4 min read

**

In this step-by-step guide, we will create a carousel component in React. The carousel will display a set of cards and allow users to scroll through them horizontally.

Requirements

Before getting started with creating the carousel component, ensure that you have the following requirements fulfilled:

  1. Tailwind CSS installed and configured in your React application.

  2. React Icons library installed in your React application.

If you haven't installed Tailwind CSS and React Icons, you can follow the official documentation for each library to set them up in your project.

Now, let's dive into creating the carousel component!

  1. Create a new component file: Create a new file called useScrollCarousel.js. This file will contain the custom hook that will handle the carousel logic.
// useScrollCarousel.js

import { useState, useRef } from "react";

const useScrollCarousel = () => {
  const [scrollPosition, setScrollPosition] = useState(0);
  const containerRef = useRef(null);

  // Function to handle scroll event
  const handleScroll = () => {
    const { scrollLeft, offsetWidth, scrollWidth } = containerRef.current;
    const maxScroll = scrollWidth - offsetWidth;
    const position =
      scrollLeft === maxScroll ? "end" : scrollLeft > 0 ? "middle" : "start";
    setScrollPosition(position);
  };

  // Function to scroll to the next item
  const scrollToNext = () => {
    const container = containerRef.current;
    if (container) {
      const nextScrollLeft = container.scrollLeft + container.offsetWidth;
      container.scrollTo({
        left: nextScrollLeft,
        behavior: "smooth",
      });
    }
  };

  // Function to scroll to the previous item
  const scrollToPrevious = () => {
    const container = containerRef.current;
    if (container) {
      const nextScrollLeft = container.scrollLeft - container.offsetWidth;
      container.scrollTo({
        left: nextScrollLeft,
        behavior: "smooth",
      });
    }
  };

  return {
    containerRef,
    handleScroll,
    scrollPosition,
    scrollToNext,
    scrollToPrevious,
  };
};

export default useScrollCarousel;
  1. Create another component file: Create a new file called ArtCard.js. This file represents an individual card within the carousel.
// ArtCard.js

import React from "react";

const ArtCard = ({ artData }) => {
  const { title, medium, price, image } = artData;

  return (
    <div className="flex flex-col gap-4 items-center rounded-lg relative w-[20rem] transform transition hover:scale-105 ease-in-out duration-500 overflow-hidden">
      <div className="rounded-lg">
        <img className="h-[20rem] object-cover" src={image} alt="" />
      </div>
      <div className="flex flex-col absolute bottom-0 bg-gray-400 w-full bg-opacity-30 px-4">
        <h1 className="font-bold">{title}</h1>
        {medium ? (
          <div className="italic text-sm">{medium}</div>
        ) : (
          <h1 className="font-bold h-4"></h1>
        )}
        <div className="font-bold">{price}</div>
      </div>
    </div>
  );
};

export default ArtCard;
  1. Create the main carousel component: Create a new file called FeatureCarousel.js. This file represents the main carousel component that utilizes the custom hook and art card component.
// FeatureCarousel.js

import React from "react";
import useScrollCarousel from "./useScrollCarousel";
import ArtCard from "./ArtCard";
import { GrNext, GrPrevious } from "react-icons/gr";

const FeatureCarousel = ({ label, data }) => {
  const {
    containerRef,
    handleScroll,
    scrollPosition,
    scrollToNext,
    scrollToPrevious,
  } = useScrollCarousel();

  return (
    <div className="flex flex-col">
      <div className="flex items-center gap-2">
        <div className="border-t-2 ml-4 lg:ml-8 h-4 border-gray-600 w-[2rem] mt-4 "></div>
        <div className="flex-shrink-0">
          <h1 className="text-left text-3xl font-semibold">{label}</h1>
        </div>
        <div className="border-t-2 h-4 border-gray-600 w-full mt-4"></div>
      </div>
      <div
        ref={containerRef}
        className="flex overflow-x-auto gap-8 py-8 px-8 items-center"
        onScroll={handleScroll}
      >
        {data.map((item) => (
          <div key={item.id} className="flex-grow-0 flex-shrink-0">
            <ArtCard artData={item} />
          </div>
        ))}
        {scrollPosition !== "start" && (
          <div className="hidden sm:block cursor-pointer">
            <GrPrevious
              className="absolute left-0 bg-gray-400 bg-opacity-50 transform -translate-y-1/2 p-2 rounded-full shadow-md h-12 w-12 "
              onClick={scrollToPrevious}
            />
          </div>
        )}

        {scrollPosition !== "end" && (
          <div className="hidden sm:block cursor-pointer">
            <GrNext
              className="absolute right-0 bg-gray-400 bg-opacity-50 transform -translate-y-1/2 p-2 rounded-full shadow-md h-12 w-12 "
              onClick={scrollToNext}
            />
          </div>
        )}
      </div>
    </div>
  );
};

export default FeatureCarousel;
  1. Use the carousel component: In your main application file or any other component where you want to use the carousel, import the FeatureCarousel component and use it with some sample data.
import React from "react";
import FeatureCarousel from "./FeatureCarousel";

const App = () => {
  // Sample data for art cards
  const artData = [
    {
      id: 1,
      title: "Art Piece 1",
      medium: "Oil on canvas",
      price: "$100",
      image: "path/to/image1.jpg",
    },
    {
      id: 2,
      title: "Art Piece 2",
      medium: "Acrylic on paper",
      price: "$200",
      image: "path/to/image2.jpg",
    },
    {
      id: 2,
      title: "Art Piece 2",
      medium: "Acrylic on paper",
      price: "$200",
      image: "path/to/image2.jpg",
    },
    {
      id: 2,
      title: "Art Piece 2",
      medium: "Acrylic on paper",
      price: "$200",
      image: "path/to/image2.jpg",
    },
    // Add more art pieces as needed
  ];

  return (
    <div>
      <FeatureCarousel label="Featured Art" data={artData} />
    </div>
  );
};

export default App;
  1. Style the carousel: You can customize the styling of the carousel and cards by modifying the CSS classes and properties in the component files (ArtCard.js, FeatureCarousel.js). Feel free to add your own CSS.

  2. Test the carousel: Start your React development server and open your application in a web browser. You should see the carousel component displaying the art cards, and you can scroll through them using the previous and next buttons.

Here's a landing page where I used this this carousel: craftdrop.vercel.app

That's it, quite easy huh! You have successfully created a carousel component in React using TailwindCSS. You can now further enhance the carousel by adding more features or customizations based on your project requirements.

Stay Ironclad! ๐Ÿฆพ

ย