A React Ref Adventure: Creating a smooth scrolling carousel using React and Tailwind CSS
**
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:
Tailwind CSS installed and configured in your React application.
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!
- 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;
- 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;
- 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;
- 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;
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.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: https://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! 🦾
Subscribe to my newsletter
Read articles from Ikenna Udemezue directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ikenna Udemezue
Ikenna Udemezue
Hi there! I'm Ikenna, a software engineer with years of experience in the industry. I'm passionate about creating high-quality software solutions that make people's lives easier and more efficient. My expertise includes front-end development, back-end development, database design, and I'm always eager to learn new technologies and tools to stay at the forefront of the rapidly-evolving software industry.