DEV Community

PhanDangKhoa96
PhanDangKhoa96

Posted on

A carousel with zooming active slide using react-spring-carousel

Hello there,

If you are a frontend developer, carousel is unavoidable. You must have faced with it at least once for sure :D So do I.

But thanks God, it is now absolutely effortless to create a carousel from many libraries such as Swiper, Slick, Owl Carousel,...

Currently i just discover a new one, which is React Spring Carousel created by Emiliano Bucci.

The final result:

React spring carousel zooming center

1. Introduction

I can not agree more with the author's motivation, which you will probably have struggles with customizing the animations, logic or the behaviors of the carousel,.. However, the React Spring Carousel can help tackle it :)

React Spring Carousel is intuitive, simple and efficient.

2. Carousel types

The author offers 2 options for creating a carousel which are:

useSpringCarousel

With this carousel you'll be able to cover most of your UI needs. You'll be able to create stunning carousels!

useTransitionCarousel

With this hook, you'll be able to create beautiful slideshows. This solution is more specific, but not less important!

I will go for the first one useSpringCarousel in this blog.

3. Let's get started coding

In this example i also use Tailwind for styling, if you are not familiar with it, you should have a look to check it out.

First, i create a simple mock item list:

const mockItems = [
        {
            id: 'item-1',
            title: 'slide 1'
        },
        {
            id: 'item-2',
            title: 'slide 2'
        },
        {
            id: 'item-3',
            title: 'slide 3'
        }
    ]
Enter fullscreen mode Exit fullscreen mode

After that i am using useSpringCarousel hook to create a simple UI slide

const {
        carouselFragment,
    } = useSpringCarousel({
        items: mockItems.map((item) => {
            return {
                ...item,
                renderItem: (
                    <div
                        className={`grid aspect-[2] w-full place-items-center text-2xl text-white bg-violet-500`}>
                        {item.title}
                    </div>
                )
            }
        })
    })
Enter fullscreen mode Exit fullscreen mode

Here is what i get:

slider carousel react spring carousel

To make the carousel more attractive, i use other options from the library to make it, like adding gap between slides, navigation, looping,..

Here is what the current code looks like:

    const {
        carouselFragment,
        slideToPrevItem, // go back to previous slide
        slideToNextItem, // move to next slide
    } = useSpringCarousel({
        itemsPerSlide: 3, // number of slides per view
        withLoop: true, // will loop
        initialStartingPosition: 'center', // the active slide will be at the center
        gutter: 24, // to add the space between slides
        items: mockItems.map((item) => {
            return {
                ...item,
                renderItem: (
                    <div
                        className={`grid aspect-[2] w-full place-items-center text-2xl text-white bg-violet-500`}>
                        {item.title}
                    </div>
                )
            }
        })
    })
Enter fullscreen mode Exit fullscreen mode

And also, we want the navigation to work, we need to add it to the markup, (for the SVG, i just quickly copy it from Hero Icons):

 <div className="py-20 relative">
            <button onClick={slideToPrevItem} className="absolute top-1/2 -translate-y-1/2 -translate-x-full left-[10%]">
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="w-6 h-6">
                    <path strokeLinecap="round" strokeLinejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
                </svg>
            </button>
            <div className="mx-auto w-[80%] overflow-x-clip py-[4%] relative">
                {carouselFragment}
            </div>
            <button onClick={slideToNextItem} className="absolute top-1/2 -translate-y-1/2 translate-x-full right-[10%]">
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="w-6 h-6">
                    <path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
                </svg>
            </button>
        </div>
Enter fullscreen mode Exit fullscreen mode

Next, for the zooming center slide, i create a state to watch the current active slide:

    const [currentSlide, setCurrentSlide] = useState(mockItems[0].id)
Enter fullscreen mode Exit fullscreen mode

After that, i am gonna use another hook
called useListenToCustomEvent destructured from useSpringCarousel to apply animation when the slide is changed

    useListenToCustomEvent((event) => {
        if (event.eventName === 'onSlideStartChange') {
            setCurrentSlide(event?.nextItem?.id)
        }
    })
Enter fullscreen mode Exit fullscreen mode

And finally, i add the condition for active slide to the items

items: mockItems.map((item) => {
            return {
                ...item,
                renderItem: (
                    <div
                        className={`grid aspect-[2] w-full place-items-center text-2xl text-white transition-all duration-700 ${currentSlide === item.id
                            ? 'z-10 scale-150 bg-yellow-600'
                            : 'bg-violet-500'
                            }`}>
                        {item.title}
                    </div>
                )
            }
        })
Enter fullscreen mode Exit fullscreen mode

And BAM, we make it, a very smooth transition, eye-catching and easy to do :D

The whole complete component code is here.

Also you can check out the whole document from Emiliano Bucci to create wonderful things. Cheers!

Top comments (0)