ReactHustle

How to Create a Custom React Card Slider Component

Jasser Mark Arioste

Jasser Mark Arioste

How to Create a Custom React Card Slider Component

Hello, hustlers! In this tutorial, you'll learn how to create a react card slider component by using the EmblaCarousel package and TailwindCSS for styling. We'll use NextJS as our react framework of choice and we'll also use Typescript for maintainability and type safety.

Final Output #

Suppose we're making a testimonial section that can be swiped right or left. By the end of this tutorial, you'll be able to build the following component. 

This is for the desktop version:

React Card Slider Desktop

Here's the mobile version:

React Card Slider Mobile Output

What is EmblaCarousel? #

Embla carousel is a lightweight carousel library with fluid motion and great swipe precision. It's perfect for building custom carousels or sliders.

Why use EmblaCarousel? #

I like using EmblaCarousel because it's very well-documented and it allows for maximum flexibility and customizability. Using it will probably cover 99% of use cases for carousel/slider implementation.

Now that you know the package we'll be using, let's start implementing!

Step 0 - Project Setup #

Let's create a new NextJS application and install the dependencies we'll be needing. Run the following command to create a new NextJS Project with Typescript and TailwindCSS configured.

npx create-next-app --ts --tailwind react-slider-tutorial

The above command will also ask you a few questions about your preferences such as ESLint, src directory, etc.

Next, let's install embla-carousel-react package

cd react-slider-tutorial
yarn add embla-carousel-react

Step 1 - Preparing the Data #

For the data, let's create the file data/testimonials.json and copy the following:

[
  {
    "author": "Jayme Petracci",
    "title": "This is awesome!",
    "content": "Lorem ipsum ...",
    "imgSrc": "https://randomuser.me/api/portraits/men/46.jpg"
  },
  {
    "author": "Liuka Kivell",
    "title": "The best tutorial!",
    "content": "Lorem ipsum ...",
    "imgSrc": "https://randomuser.me/api/portraits/men/48.jpg"
  },
  {
    "author": "Chrysler Grinikhinov",
    "title": "Revenue increased by 50%",
    "content": "Lorem ipsum ...",
    "imgSrc": "https://randomuser.me/api/portraits/men/49.jpg"
  },
  {
    "author": "Kessiah Cornbell",
    "title": "Lorem ipsum",
    "content": "Lorem ipsum ...",
    "imgSrc": "https://randomuser.me/api/portraits/men/50.jpg"
  },
  {
    "author": "Wash Pont",
    "title": "The best overall service",
    "content": "Lorem ipsum ...",
    "imgSrc": "https://randomuser.me/api/portraits/men/51.jpg"
  }
]
1234567891011121314151617181920212223242526272829303132

Later, we'll import this when populating our Card component.

Step 2 - Creating the Card Component #

Next, let's create a simple <Card/> component. Create the file components/TestimonialCard.tsx. This component is a purely display component and does not have any behavior. Note that you don't have to copy this, I used testimonial card from tailwind components as a reference (Credits to the owner). You can create any card component as you wish.

import Image from "next/image";
import Link from "next/link";

type Props = {
  title: string;
  imgSrc: string;
  content: string;
  author: string;
};

const TestimonialCard = (props: Props) => {
  return (
    <div className="py-4 px-8 bg-white shadow-lg rounded-lg my-20">
      <div className="flex justify-center md:justify-end -mt-16">
        <Image
          alt={props.author}
          className="w-20 h-20 object-cover rounded-full border-2 border-indigo-500"
          height={80}
          width={80}
          src={props.imgSrc}
        />
      </div>
      <div>
        <h2 className="text-gray-800 text-3xl font-semibold">{props.title}</h2>
        <p className="mt-2 text-gray-600">{props.content}</p>
      </div>
      <div className="flex justify-end mt-4">
        <Link href="#" className="text-xl font-medium text-indigo-500">
          {props.author}
        </Link>
      </div>
    </div>
  );
};
export default TestimonialCard;
1234567891011121314151617181920212223242526272829303132333435

Step 3 - Creating the Slider Component #

Next, let's create the slider/carousel component. Create the file components/Slider.tsx and copy the code below. I added comments so make sure you don't skip them.

import useEmblaCarousel, { EmblaOptionsType } from "embla-carousel-react";
import { PropsWithChildren } from "react";

// 1. define the props
type Props = { options?: EmblaOptionsType } & PropsWithChildren;

const Slider = ({ children, options }: Props) => {
  // 2. initialize EmblaCarousel using the custom hook
  const [emblaRef] = useEmblaCarousel({
    slidesToScroll: 1,
    align: "start",
    ...options,
  });

  return (
    // 3. set ref as emblaRef.
    // make sure we have overflow-hidden and flex so that it displays properly
    <div className="overflow-hidden" ref={emblaRef}>
      <div className="flex gap-10">{children}</div>
    </div>
  );
};
export default Slider;
1234567891011121314151617181920212223

Explanation:

We created a reusable Slider component that doesn't need to have knowledge of its contents by using props.children. Later, when integrating, you can see that the card component doesn't matter as you'll be able to use any card as you wish.

If you need a more complex example such as having buttons and dots/thumbnails, check out my other tutorial: How to Create a Carousel in NextJS using TailwindCSS and EmblaCarousel. It covers a more in-depth explanation of the implementation.

Step 4 - Integrating Both Components #

Next, let's integrate both components into the pages/index.tsx file. The pages/index.tsx file represents the "/" route in NextJS.

// pages/index.tsx
// 1. import all the necessary components and data
import Slider from "@/components/Slider";
import TestimonialCard from "@/components/TestimonialCard";
import testimonials from "@/data/testimonials.json";

export default function Home() {
  return (
    <main
      className={`flex min-h-screen flex-col items-center justify-between py-24`}
    >
      {/* 2. make sure our carousel container takes up the full screen width using w-screen */}
      <div className="w-screen">
        <Slider options={{ align: "center" }}>
          {testimonials.map((testimonial, i) => (
            // 3. flex-[0_0_50%] set the width of each card to 50% of the viewport
            // for mobile devices we use 90% width
            <div key={i} className="flex-[0_0_90%] md:flex-[0_0_50%]">
              <TestimonialCard {...testimonial} />
            </div>
          ))}
        </Slider>
      </div>
    </main>
  );
}
1234567891011121314151617181920212223242526

You can change the width of the card by modifying the flex-[0_0_xx%] class depending on your requirements. In line 14, we used a custom option {align:"center} so that each card will be aligned at the center when swiping but you can check more options in the documentation.  

That's basically it!

Full Code and Demo #

The full code is available on my GitHub page: jmarioste/react-card-slider-tutorial

The demo is available on Stackblitz: React Card Slider Tutorial

Conclusion #

You learned how to create a react card slider by using EmblaCarousel and TailwindCSS library. We only covered a basic example but there's a lot more you can do by checking out their examples.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.

Resources #

Share this post!

Related Posts

Disclaimer

This content may contain links to products, software and services. Please assume all such links are affiliate links which may result in my earning commissions and fees.
As an Amazon Associate, I earn from qualifying purchases. This means that whenever you buy a product on Amazon from a link on our site, we receive a small percentage of its price at no extra cost to you. This helps us continue to provide valuable content and reviews to you. Thank you for your support!
Donate to ReactHustle