Creating a Beautiful Looping Image Carousel with CSS and JavaScript

Creating a carousel with HTML, CSS, and JavaScript can be a fun and rewarding project for web developers. In this blog post, we'll explore the steps involved in creating a carousel and break it down into smaller tasks to make it easier to understand and implement.

This is what we will build

Demo GIF

Pretty cool, huh?

Task 1: Creating a straight row with all the images lined horizontally centered

To start, we need a row of images that are horizontally centered. We can accomplish this by using CSS Flexbox. Here are the steps involved:

  1. Create a section with the below styles, so that everything inside it is placed horizontally and vertically centered.

     section{  
       height:100%;
       display:flex;  
       align-items:center;  
       justify-content:center;
     }
    
  2. Create a container div with the class carousel, which contains all the images. We will also make this a flex item, and give it a max-width (optional).

    
     <section>
         <div class="carousel">
           <!-- Insert images here -->
         </div>
     </section>
    
  3. Set the justify-content property of the container div to "center" to center all the images horizontally.

  4. Set the gap property of the container div to add some space between the images.

     .carousel {
       display: flex;
       max-width:1000px;
       gap:20px;      
     }
    
  5. Let's also add the transition to carousel, as we will need this for animating the slide effect. The class sliding-transition will be added and removed using Javascript.

     .carousel.sliding-transition {
       transition: transform 0.5s ease-in-out;
     }
    

Task 2: Adding the Images

We will be using images from the free website picsum.photos (The Lorem Ipsum for photos.)

  1. Add <img> inside the carousel, and give them a class carousel-image

      <div class="carousel">
        <img src="https://picsum.photos/id/23/500" alt="Image 1" class='carousel-image'>
        <!-- Rest of the images in similar fashion -->
     </div>
    
  2. Add any CSS you want, for styling the images. I will just go ahead with some box-shadow. (P.S. If you're facing problems with setting the width of the images, try using flex-basis instead.)

     .carousel-image {
       -webkit-box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, 0.5);
       -moz-box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, 0.5);
       box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, 0.5);
     }
    

Task 3: Adding the background image with the blur and other effects

To make the carousel visually interesting, we can add a background image with a blur effect. We will place the currently selected image as the background image itself. Here's how to do it:

  1. Create an <img /> element with the class bg-image.

     <section>
       <img ... class='bg-image' />
         <div class="carousel">
          <!-- images here -->
         </div>    
     </section>
    
  2. Set the width and height of the image to 100% to make it fill the entire screen.

  3. Add a blur effect using the CSS property filter and set it to blur(8px).

  4. We will also put a position: absolute and inset:0 so that the image is placed behind the carousel. Added some other CSS which are for styling the image.

     .bg-image {
       position:absolute;
       inset:0;
       width:100%;
       height:100%;
       filter: blur(8px);
       -webkit-filter: blur(8px);
       transform:scale(1.1);
       object-fit:cover;
     }
    

Task 4: Designing the buttons for the left arrow and the right arrow

To allow users to navigate through the images, we need to create arrow buttons. Here's how to do it:

  1. Create two buttons with the classes left-arrow and right-arrow, with arrow-button being common.

  2. We need to position them absolute, and for that, we will need a div with position: relative.

  3. Create a div with class carousel-container which will contain the carousel and the buttons.

     .carousel-container {
       position: relative;
       overflow: hidden;
     }
    
     <section>
       <img ... class='bg-image' />
       <div class="carousel-container">
         <div class="carousel">
           <!-- images here -->
         </div>
         <button class="arrow-button left-arrow"></button>
         <button class="arrow-button right-arrow"></button>
       </div>
     </section>
    
  4. Set the top of the buttons to 50% and use the transform: translateY(-50%) property to vertically center them.

  5. Give the buttons a circular shape using the border-radius property.

  6. These are the CSS used to add some extra look and feel.

     .arrow-button {
       padding: 0;
       position: absolute;
       top: 50%;
       transform: translateY(-50%);
       color: #000;
       cursor: pointer;
       background: rgb(255, 255, 255, 0.3);
       width: 36px;
       font-size: 28px;
       display: flex;
       justify-content: center;
       align-items: center;
       border: none;
       border-radius: 50%;
       aspect-ratio: 1;
       -webkit-box-shadow: 5px 5px 5px -2px rgba(0, 0, 0, 0.5);
       -moz-box-shadow: 5px 5px 5px -2px rgba(0, 0, 0, 0.5);
       box-shadow: 5px 5px 5px -2px rgba(0, 0, 0, 0.5);
     }
    
  7. We will use Unicode to create the arrows : &#8249; and &#8250;. Put them inside a span, with a width and height of 100%;

     span {
       height: 100%;
       width: 100%;
     }
    
     .left-arrow {
       left: 20px;
     }
    
     .right-arrow {
       right: 20px;
     }
    
     <button class="arrow-button left-arrow"><span>&#8249;</span></button>
     <button class="arrow-button right-arrow"><span>&#8250;</span></button>
    

Task 4: Creating the JavaScript to change the current image.

Bear with me, we are almost done. Phew!

  1. These are all the initializations:

     const carousel = document.querySelector(".carousel");
     const backgroundImage = document.querySelector(".bg-image");
    
     const leftArrow = document.querySelector(".left-arrow");
     const rightArrow = document.querySelector(".right-arrow");
    
     let currentIndex = 0;
     let prevIndex;
     const images = document.querySelectorAll(".carousel-image");
    
     const totalImages = Object.keys(images).length;
    
     // const imageWidth = images[1].getBoundingClientRect().x;
     const imageWidth = 520;
    

    I am using a constant value of image width of 520 pixels, since there were some issues with Javascript loading late and calculating the width incorrectly in CodePen. I have commented the ideal approach for calculating width using getBoundingClientRect().

    P.S. 520 Since <img> is 500 pixels wide and the flex box has a gap of 20px.

  2. Here's the Pseudo Code for the Right Arrow :

     1. When right arrow button is clicked, set prevIndex = currentIndex.
     2. Set currentIndex = (currentIndex + 1) % totalImages
     3. Now, to have the animation part, we will add the class `sliding-transition` to carousel.
     4. Move the carousel to the left by the width of one image using `translateX(-imageWidth pixels)`.
     5. Set the background image to the new current image.
     6. After the transition is completed:
        1. Move the prevIndex image to the end of `carousel` DOM.
        2. Remove the class `sliding-transition` from carousel.
        3. Remove the transform property as well, since we re-ordered the DOM.
    

    By removing the transition class, we ensure that the transition only occurs when we want it to and that we have full control over the carousel's movement.

     rightArrow.addEventListener("click", () => {
       carousel.classList.add("sliding-transition");
    
       prevIndex = currentIndex;
       currentIndex = (currentIndex + 1) % totalImages;
    
       carousel.style.transform = `translateX(-${imageWidth}px)`;
       backgroundImage.src = images[currentIndex].src.slice(0, -3) + "1000";
    
       setTimeout(() => {
         carousel.appendChild(images[prevIndex]);
         carousel.classList.remove("sliding-transition");
         carousel.style.transform = "";
       }, 500);
     });
    
  3. Now, here is the Pseudo Code for the Left Arrow (a tad bit more complex than the Right Arrow) :

     1. When left button is clicked, set prevIndex = currentIndex.
     2. Set currentIndex = (currentIndex - 1 + totalImages) % totalImages
     Why modulo?
     In case currentIndex = 0, we need to do modulo, so as to implement the cyclical images.
     3. Move the carousel to the left by the width of one image using `translateX(-imageWidth pixels)`.
     4. Move the currentIndex image to the beginning of `carousel` DOM.
     5. Now, to have the animation part, we will add the class `sliding-transition` to carousel.
     6. Now make the carousel move to the right by width of one image (basically setting `translateX(0)`), or you can remove the transform property as well.
     7. Set the background image to the new current image.
     8. After the transition is completed, remove the class `sliding-transition` from carousel. (This can be done using timeout matching the animation's duration)
    
     leftArrow.addEventListener("click", () => {
       prevIndex = currentIndex;
       currentIndex = (currentIndex - 1 + totalImages) % totalImages;
    
       // Move Carousel to the left by one image, and insert the image at currentIndex at the beginning of carousel's DOM
       carousel.style.transform = `translateX(-${imageWidth}px)`;
       carousel.insertBefore(images[currentIndex], carousel.firstChild);
    
       // Now, let's start the transition effect, from -520 px to 0 px.
       setTimeout(() => {
         carousel.style.transform = "";
         carousel.classList.add("sliding-transition");
    
         // Changing the background Image
         backgroundImage.src = images[currentIndex].src.slice(0, -3) + "1000";
       }, 10);
    
       setTimeout(() => {
         // By removing the transition class, we ensure that the transition only occurs when we want it to and that we have full control over the carousel's movement.
         carousel.classList.remove("sliding-transition");
       }, 490);
     });
    

Here's the CodePen if you want to see the full code and mess around with it.

In conclusion, creating a carousel involves using HTML, CSS, and JavaScript to position and animate a series of images. By breaking down the process into smaller tasks, we can make it easier to understand and implement.

1
Subscribe to my newsletter

Read articles from Arindam Chowdhury directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Arindam Chowdhury
Arindam Chowdhury

I am a Frontend Developer from India. I have 4+ years of experience in React JS, and I will continue to share beginner friendly blogs.