Create an image carousel with user controls

Reading Time: 6 minutes 🕑

Last updated: November 26, 2021.

In this tutorial, we will cover how to create a rotating image carousel using HTML, CSS and vanilla JavaScript.

In the carousel we will build, the feature image will rotate every two seconds and the user will able to navigate backwards and forwards through the images.

Let’s get started!

The HTML markup

Here is the basic markup we will be working with (explanation below):

<div id="carousel-container">
        <div id = "image-container">
            <img src="https://images.unsplash.com/photo-1485081669829-bacb8c7bb1f3?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=750&q=80">
            <img src="https://images.unsplash.com/photo-1530841377377-3ff06c0ca713?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=750&q=80">
            <img src="https://images.unsplash.com/photo-1471989749605-1d14cb3d836e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=779&q=80">
            <img src="https://images.unsplash.com/photo-1581951756710-084ff9f7b0ca?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
        </div>
        <div class="user-controls">
            <button id = "previous">Previous</button>
            <button id = "next">Next</button>
        </div>
</div>

We wrap everything to do with the carousel within a div element with an id of carousel-container.

Within this container div, there are two nested div element: one to contain the images (id = image-container) and another for user controls (id = user-controls).

For the div element containing the images, insert as many images as you want to appear in the carousel. For this carousel, we insert 4 images of European beauty hotspots from Unsplash.

In the user-controls div element, we place two buttons: one that displays “previous” and another “next” and give each these names as an id.

CSS styling

To style the carousel as it appears in the project preview, add the following CSS.

Note that some of this CSS is necessary for the carousel to function correctly and not just for styling: the CSS is used to hide images that are prior or upcoming in the slideshow. Also the image and container dimensions must be correctly set in relation to each other (see notes):

        /* Imports 'Caveat' font from Google library */
    @import url('https://fonts.googleapis.com/css2?family=Caveat&display=swap');
        
        body {
            background: white;
            /* Set background */
            background-repeat: no-repeat;
            background-position: top left;
            margin: 0px; /* Prevents vertical scrolling */
            height: 100vh;
            /* Flex for perfect centering */
            display: flex;
            justify-content: center;
            align-items: center;
        }
        img { /* sets image dimensions */
            width: 600px;
            height: 400px;
            object-fit: cover; /* makes image cover these dimensions */
        }

        #carousel-container { /* set dimensions for enitre carousel container */
            width: 600px;
            height: 440px; /* +30px to make space for user controls */
            overflow: hidden; /* Prevents seeing previous and next images  */
            box-shadow: rgba(0, 0, 0, 0.4) 0px 30px 90px;
        }

        #image-container {
            /* flex properties set images to appear in a row
            with no wrapping to a new line. Images keep original
            size as these are fixed */
            display: flex;
            flex-direction: row;
            flex-wrap: none;
            /* Manages transition */
            transition: transform 1s ease-in-out;
        }

        #user-controls { 
            /* Buttons along rows with space between */
            display: flex;
            flex-direction: row;
            justify-content: space-between;
        }
        #previous, #next {
            /* Buttons each take up 50% of row width */
            margin: 0px;
            width: 50%;
            height: 40px;
            /* Buttons styling */
            font-family: 'Caveat', cursive;
            background-color: rgb(139, 0, 139);
            color: whitesmoke;
            border: 1px solid grey;
            border-radius: 0px;
            font-size: 1.6rem;
            padding-top: 0px;
        }

Your slideshow should now look something like the image below. But it is completely static! To animate it, we are going to slide through the images, from left to right, using JavaScript.

Animating the carousel with JavaScript

Automatic rotation

To slide through the images in the show, we manipulate the CSS value of transform: translateX(0px). Concretely, we set this to decrease the width of an image every few seconds. This will slide the images to the left by the width of an image, revealing the next image.

We start by selecting the image container and all images and saving these into the variables imageContainer and images.

We then create an index variable holding the value of where we should be in the show at any time.

To program the animation of the slideshow, we create a new function called runCarousel and call it every four seconds using setInterval.

    // Select DOM elements
    const imageContainer = document.getElementById('image-container');
    const images = document.querySelectorAll('img');

    // Create a index counter
    let index = 0;
    
    // Set the function runCarousel to be called
    // every 4 seconds
    let interval = setInterval(runCarousel, 4000);

    function runCarousel() {
       // carousel functionality here
    }

Now, within the runCarousel function, we want to increase the value of index by 1 each time it is called and then change the image. We also want to make sure that if index reaches an out of bounds value (no more images left or less than 0), it is set to 0 (the beginning of the show).

Here is how we program this functionality:

    // Select DOM elements
    const imageContainer = document.getElementById('image-container');
    const images = document.querySelectorAll('img');

    // Create a index counter
    let index = 0;
    
    // Set the function runCarousel to be called
    // every 4 seconds
    let interval = setInterval(runCarousel, 4000);

    function runCarousel() {
        index++ // increase index by 1
        checkOutBoundConditions() // check if out of bounds
        changeImage() // change image to new index value
    }

    function checkOutBoundConditions() {
        // If index reaches the end, set
        // index to 0 again (recall index
        // starts from 0)
        if(index === images.length) {
            index = 0
        }
        // If index is less than 0, set
        // to 0
        else if (index < 0) {
            index = 0
        }
    }

    function changeImage() {
        // Negative value on translateX shifts images left,
        // so show animates by multiplying the width of an 
        // image by index value
        imageContainer.style.transform = `translateX(${-index * 600}px)`
    }

By adding the above JavaScript, the slideshow will be animated automatically. Next we look at how to program the user controls.

Activating user controls

The user controls are activated by adding the following code:

   const prevBtn = document.getElementById('previous');
    const nextBtn = document.getElementById('next');

    nextBtn.addEventListener('click', () => {
        // reset interval
        clearInterval(interval);
        interval = setInterval(runCarousel, 3000);
        // increase counter by 1
        index++;
        // Run index value through out of bounds 
        // check and then run change image with nex
        // index value
        checkOutBoundConditions();
        changeImage()
    })

    prevBtn.addEventListener('click', () => {
        // reset interval
        clearInterval(interval);
        interval = setInterval(runCarousel, 3000);
        // decrease counter by 1
        index--;
        // Out of bounds check and then change image
        // with new index value
        checkOutBoundConditions();
        changeImage()
    });

For each button, a ‘click’ event listener is added. Within each function, the interval is cleared are restarted (because a user’s click of a button should restart the clock on the next or previous image). Then value of the counter is either increased (next) or decreased (previous) by 1. Now, all that is left to do is to run the value of index through the out of bounds check function and then run the change image function, which will animate to slideshow to move to the new value of index.

The complete JavaScript code:

    // Select DOM elements
    const imageContainer = document.getElementById('image-container');
    const images = document.querySelectorAll('img');

    // Create a index counter
    let index = 0;
    
    // Set the function runCarousel to be called
    // every 4 seconds
    let interval = setInterval(runCarousel, 4000);

    function runCarousel() {
        index++ // increase index by 1
        checkOutBoundConditions()
        changeImage() // change image to new index value
    }

    function checkOutBoundConditions() {
        // If index reaches the end, set
        // index to 0 again (recall index
        // starts from 0)
        if(index === images.length) {
            index = 0
        }
        // If index is less than 0, set
        // to 0
        else if (index < 0) {
            index = 0
        }
    }

    function changeImage() {
        // Negative value on translateX shifts images left,
        // so show animates by multiplying the width of an 
        // image by index value
        imageContainer.style.transform = `translateX(${-index * 600}px)`
    }

    const prevBtn = document.getElementById('previous');
    const nextBtn = document.getElementById('next');

    nextBtn.addEventListener('click', () => {
        // reset interval
        clearInterval(interval);
        interval = setInterval(runCarousel, 3000);
        // increase counter by 1
        index++;
        // Run index value through out of bounds 
        // check and then run change image with nex
        // index value
        checkOutBoundConditions();
        changeImage()
    })

    prevBtn.addEventListener('click', () => {
        // reset interval
        clearInterval(interval);
        interval = setInterval(runCarousel, 3000);
        // decrease counter by 1
        index--;
        // Out of bounds check and then change image
        // with new index value
        checkOutBoundConditions();
        changeImage()
    });

Summary

In this tutorial we have covered how to create an image slideshow using HTML, CSS and JavaScript.

For more projects, check out our projects section!