DEV Community

Cover image for How to build a Carousel from scratch
Jay Cruz
Jay Cruz

Posted on

How to build a Carousel from scratch

Featuring JavaScript, HTML, and CSS.

Carousel

What is a Carousel?

In Web Development, a carousel is a feature that displays a collection of different items (usually images) in a slideshow-like manner. They usually include a couple of arrow buttons that control back and forth navigation through this collection. When the end of the collection or last item is reached it circles back around to the beginning, hence the term carousel.

Some common use cases are image galleries, news headlines, or featured articles on the homepage of a website.

Thinking about how to build a Carousel

To begin building a carousel we should first start thinking about what we want our carousel to look like and what are the main features it will need. Some of the main points to think about are the following.

  • The basic HTML structure needed to build off of

  • Including previous and next buttons for navigation (arrow buttons)

  • What are the types of items we’ll be including as our slides? (zombie images in this case)

  • Displaying which slide the user is currently on (filled in dots)

  • Functionality for changing to the next or previous slide (Javascript)

  • Styling of our carousel (CSS)

  • Accessibility of our carousel (Use aria labels )

With this in mind, we can begin building out our carousel.

Building a Carousel

To start building out the structure for our carousel we’ll use several HTML divs so we can position it how we need it to be displayed. The first div will be the container to hold all of the items and features. Each item and feature should also be wrapped in its own div. This includes the images, buttons, and dots.

We’ll also give the first item a class carousel-item-visible for displaying a default image. We’ll utilize this later for displaying the image a user is currently viewing. We can also do the same thing for the dots giving the first dot a class selected-dot and setting it to checked.

<html>
    <head>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <div class="carousel">
            <div class="carousel-item carousel-item-visible">
                <img src="https://images.unsplash.com/photo-1537211261771-e525b9e4049b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&h=450&q=80" 
                     alt="Squirrel zombie" />
            </div>
            <div class="carousel-item">
                <img src="https://images.unsplash.com/photo-1503925802536-c9451dcd87b5?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&h=450&q=80" 
                     alt="Zombie hands" />
            </div>
            <div class="carousel-item">
                <img src="https://images.unsplash.com/photo-1509558567730-6c838437b06b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=600&h=450&q=80" 
                     alt="Zombie pumpkin" />
            </div>
            <div class="carousel-actions">
                <button id="carousel-button-prev" aria-label="Previous"><</button>
                <button id="carousel-button-next" aria-label="Next">></button>
            </div>
            <div class="carousel-dots">
                <input class="dot selected-dot" type="radio" name="dot" checked />
                <input class="dot" type="radio" name="dot" />
                <input class="dot" type="radio" name="dot" />
            </div>
        </div>

        <script src="index.js"></script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Next, we want to add styling to make the layout appear how we want it to look. We also want to have our images displayed and navigated through in a smooth and user-friendly fashion so we utilize CSS keyframes for that.

.carousel {
    max-width: 600px;
    position: relative;
    margin: 0 auto;
}

.carousel .carousel-item,
.carousel .carousel-item-hidden {
    display: none; /* hide all slide images not currently being viewed */
}

.carousel .carousel-item-visible {
    display: block; /* show current slide image */
    animation: fadeVisibility 0.5s; /* for fading effect when switching between slides */
}

.carousel .carousel-item img {
    width: 100%;
    max-width: 600px;
    height: auto;
}

/* Navigation control styles */
.carousel .carousel-actions {
    display: flex;
    width: 100%;
    justify-content: space-between; /* put space between the navigation buttons */
    position: absolute; /* position navigation buttons on top */
    top: 50%; /* center navigation buttons on the slide */
    transform: translateY(-50%); /* align navigation buttons */
}

.carousel .carousel-actions button {
    border-radius: 50px;
    background-color: white;
    border: 0;
    font-size: 16px;
    font-weight: bold;
    cursor: pointer;
    width: 40px;
    height: 40px;
}

.carousel .carousel-actions button#carousel-button-prev {
    margin-left: 20px; /* prevent previous button from touching the side*/
}

.carousel .carousel-actions button#carousel-button-next {
    margin-right: 20px;  /* prevent next button from touching the side*/
}

.carousel-dots {
    text-align: center; 
}

.dot {
    opacity: 0.7; /* gray out dots for slides not being visted */
}

.dot:focus {
    border: 1px solid black; /* dot for currently visited slide */
}

/* hanlde smooth transitions between slides */
@keyframes fadeVisibility {
    0% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now that we have our structure and styling completed for the carousel we can put some life into it. We’ll need to use Javascript to build the functionality for allowing back and forth navigation through our collection of images.

First, we’ll grab all of the moving parts of the carousel that will be needed from the DOM. This includes all of the slides, the next button, the previous button, and the dots. Next, we need a way to keep track of and set the current slide position we’re on and a reference to the total number of slides.

const slides = document.getElementsByClassName("carousel-item");
const nextButton = document.getElementById("carousel-button-next");
const prevButton = document.getElementById("carousel-button-prev");
const dots = document.getElementsByClassName("dot");
let position = 0;
const numberOfSlides = slides.length;
Enter fullscreen mode Exit fullscreen mode

From there we can start to think about the logic for controlling the back and forth movement of changing image slides. One important thing to note is that we should only be viewing one slide at a time so we’ll need a way to hide all other slides besides the one at the current position. For this we can use a helper function, we’ll call it hideAllSlides() .

function hideAllSlides() {
    // remove all slides not currently being viewed
    for (const slide of slides) {
        slide.classList.remove("carousel-item-visible");
        slide.classList.add("carousel-item-hidden");
    }
}
Enter fullscreen mode Exit fullscreen mode

Now we can utilize our helper function inside of our slide navigation functions which we’ll be building shortly!

Let’s implement our navigation functions to control slide movement, we’ll call them handleMoveToNextSlide() and handleMoveToPrevSlide() . For each function that handles moving to the previous or next slide, we’ll first call our helper hideAllSlides() inside of the function so we don’t get multiple slides rendering at once when they are invoked.

const handleMoveToNextSlide = function(e) {
    hideAllSlides();
}

const handleMoveToPrevSlide = function(e) {
    hideAllSlides();
}
Enter fullscreen mode Exit fullscreen mode

Afterward, we’ll need to set up conditionals that check the current slide position so we know which way to move.

For the next slide, it will be a check for if we’ve reached the end and in that case, we reset back to the first slide. The previous slide will be the exact opposite, moving to the last slide once we’ve reached the first. The final task would be to set the current slide by adding the class name carousel-item-visible to the slide at the updated position, then to add the selected-dot class to the dot at the same position and set it to be checked.

const handleMoveToNextSlide = function(e) {
    hideAllSlides();

    // check if last slide has been reached
    if (position === numberOfSlides - 1) {
        position = 0; // go back to first slide
    } else {
        // move to next slide
        position++;
    }
    // make current slide visible
    slides[position].classList.add("carousel-item-visible");

    // update dot to represent current slide
    dots[position].classList.add("selected-dot");
    dots[position].checked = true;
}

const handleMoveToPrevSlide = function(e) {
    hideAllSlides();

    // check if we're on the first slide
    if (position === 0) {
        position = numberOfSlides - 1; // move to the last slide
    } else {
        // move back one
        position--;
    }
    // make current slide visible
    slides[position].classList.add("carousel-item-visible");

    // update dot to represent current slide
    dots[position].classList.add("selected-dot");
    dots[position].checked = true;
}
Enter fullscreen mode Exit fullscreen mode

Just one last step!

Let’s add in the event listeners to listen for each click event on the previous and next slide buttons, passing in our handleMoveToNextSlide() and handleMoveToPrevSlide() as the callbacks.

nextButton.addEventListener("click", handleMoveToNextSlide);
prevButton.addEventListener("click", handleMoveToPrevSlide);
Enter fullscreen mode Exit fullscreen mode

And that’s all folks!

Interact with the code pen for our finished zombie images carousel below:

Resources

Discussion (0)