Awesome Guide to Your First Product Carousel in 2025!
Awesome Guide to Your First Product Carousel in 2025!

Awesome Guide to Your First Product Carousel in 2025!18 min read

  Reading time 22 minutes

Ever wondered how e-commerce sites showcase their products so elegantly? Often, they use a sleek, interactive product carousel. It looks complex, but what if I told you that you could build one yourself? 😊

In this guide, we’ll break down how to create a beautiful and animated product carousel using nothing but HTML, CSS, and a sprinkle of modern JavaScript. It’s a fantastic project for beginners to get comfortable with DOM manipulation and CSS animations.

Ready to build something awesome? Let’s get started!


Awesome Guide to Your First Product Carousel in 2025!
Awesome Guide to Your First Product Carousel in 2025!

Our goal today is to build a product carousel that not only switches between images but does so with a stylish, smooth animation involving colored overlays.

Setting Up the Foundation: The HTML Structure

First things first, let’s create the skeleton of our carousel with HTML. This structure is simple but very effective. We need a main container, a place for our images (slides), colored bars (overlays), and the navigation links.

Here’s what the HTML looks like:

HTML

<div class="carousel">
  <div class="slides">
    <img
      src="https://webdevservices.in/cdn/1.png"
      alt="Product Carousel Image 1: Stainless Steel"
      class="active"
    />
    <img
      src="https://webdevservices.in/cdn/2.png"
      alt="Product Carousel Image 2: Army Green"
    />
    <img
      src="https://webdevservices.in/cdn/3.png"
      alt="Product Carousel Image 3: Cranberry"
    />
    <img
      src="https://webdevservices.in/cdn/4.png"
      alt="Product Carousel Image 4: Midnight Blue"
    />
  </div>

  <div class="overlays">
    <div class="bar" style="--bar-color: #bdc3c7;"></div>
    <div class="bar" style="--bar-color: #218c74;"></div>
    <div class="bar" style="--bar-color: #dd6b7b;"></div>
    <div class="bar" style="--bar-color: #30465c;"></div>
  </div>

  <ul class="nav-links">
    <li><a href="#" class="nav-link">Stainless Steel</a></li>
    <li><a href="#" class="nav-link">Army Green</a></li>
    <li><a href="#" class="nav-link">Cranberry</a></li>
    <li><a href="#" class="nav-link">Midnight Blue</a></li>
  </ul>
</div>

Breaking it Down:

  • <div class="carousel">: This is our main wrapper that holds everything together.
  • <div class="slides">: This div contains all our product images (<img>). We’ll use CSS and JavaScript to show only one at a time. Notice the first image has an active class—this tells us it’s the one to display initially.
  • <div class="overlays">: This holds the colored bar divs. These will be used to create a cool wipe animation during transitions. We’re using a CSS custom property (--bar-color) to set the color for each bar.
  • <ul class="nav-links">: This is a simple unordered list containing the links that the user will click to switch between slides.


Bringing it to Life: The CSS Styling

Now for the fun part—making it look good! Our CSS will handle the layout, initial visibility, and the basic styles for our navigation links.

We’ll use position: absolute to stack our images and overlays on top of each other. This is key to making the carousel work.

CSS

/* Importing a nice font from Google Fonts */
@import url("https://fonts.googleapis.com/css?family=Lora:400,400i,700");

body {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  min-height: 100vh;
  margin: 0;
  font-family: Lora, serif;
}

.carousel {
  position: relative;
  display: flex;
}

/* --- Slides (The Images) --- */
.carousel .slides {
  position: relative;
  top: -4em;
  left: 10em;
}

.carousel .slides img {
  position: absolute;
  width: 450px;
  height: 450px;
  opacity: 0; /* All images are hidden by default */
  z-index: 999;
}

.carousel .slides img.active {
  opacity: 1; /* Only the active image is visible */
}

/* --- Overlays (The Color Bars) --- */
.carousel .overlays {
  position: relative;
  width: 36em;
  height: 18em;
}

.carousel .overlays .bar {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: var(--bar-color);
  transform-origin: left; /* Animation will happen from the left */
}

/* --- Navigation --- */
.carousel .nav-links {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  margin: 0;
  padding: 0 0 0 6em;
  list-style-type: none;
}

.carousel .nav-links .nav-link {
  font-size: 2rem;
  line-height: 2;
  text-decoration: none;
  color: #7f8c8d;
  transition: 0.3s;
}

.carousel .nav-links .nav-link:hover {
  color: #1c1e1f;
}

.carousel .nav-links .nav-link.active {
  color: black;
  pointer-events: none; /* Can't click the active link again */
}

Key CSS Concepts Explained:

  • Positioning: We set .carousel to position: relative so we can use position: absolute on its children (.slides img and .overlays .bar) to place them precisely within the carousel’s boundaries.
  • Hiding & Showing Slides: All images have opacity: 0 by default, making them invisible. We only add opacity: 1 to the image that has the .active class. This is the core mechanism for switching slides.
  • CSS Custom Properties: Using var(--bar-color) allows us to set the background color of each bar directly in the HTML. This is a clean way to manage different styles without writing extra CSS classes. For more on this, check out the MDN guide on CSS Custom Properties.
  • transform-origin: left: This tells the browser that any transformations (like scaling) on the .bar elements should start from the left edge. This is crucial for our wipe animation.


Making it Interactive: The JavaScript Magic

This is where we add the brains to our product carousel. The JavaScript will listen for clicks on our navigation links and then orchestrate the animations to switch between slides. We’ll be using the modern Web Animations API, which is a powerful and easy-to-use tool for creating animations in JavaScript. If you want to dive deeper, you can explore it further on the Web Animations API documentation page.

Let’s break down the script, step by step.

Step 1: Selecting Our Elements

First, we need to grab all the HTML elements we want to work with: the navigation links, the image slides, and the overlay bars.

JavaScript

var navLinks = document.querySelectorAll(".carousel .nav-link");
var slides = document.querySelectorAll(".carousel .slides img");
var overlays = document.querySelectorAll(".carousel .bar");

document.querySelectorAll returns a NodeList (which is like an array) of all elements that match the given CSS selector.

Step 2: Setting the Initial State

We need to make sure that when the page loads, the first slide and its corresponding navigation link are marked as “active.”

JavaScript

var maxZIndex = navLinks.length; // Used to layer overlays correctly
var easeInOutQuart = "cubic-bezier(0.77, 0, 0.175, 1)";

// Make the first slide and nav link active on page load
slides[0].classList.add("active");
navLinks[0].classList.add("active");

We also define a variable maxZIndex to help us manage the stacking order (z-index) of our overlay animations.

Step 3: Adding the Click Events

Next, we need to loop through each navigation link and add an event listener. This listener will wait for a “click” and then run our animation code.

JavaScript

navLinks.forEach(function (navLink, activeIndex) {
  // Set the initial z-index for each overlay bar
  overlays[activeIndex].style.zIndex = navLinks.length - activeIndex;

  navLink.addEventListener("click", function () {
    // All our animation logic will go inside here!
  });
});

The forEach loop gives us two important things: the navLink itself and its activeIndex (its position in the list, e.g., 0, 1, 2, 3). This index is crucial because it tells us which slide and overlay correspond to the clicked link.

Step 4: Animating the Slides

Inside the click event listener, the first thing we do is handle the slide transition. This is a two-part process: fade out the old slide, and then fade in the new one.

JavaScript

// ...inside the click event listener

// 1. Update the active class on the nav links
navLinks.forEach(function (navLink) { 
  navLink.classList.remove("active"); 
});
navLink.classList.add("active");

// 2. Find the current active slide
var currentSlide = document.querySelector(".carousel .slides img.active");

// 3. Animate the current slide out
var slideFadeOut = currentSlide.animate([
    { transform: "translateX(0)", opacity: 1 },
    { transform: "translateX(5%)", opacity: 0 }
], {
    duration: 600,
    easing: "ease-in",
    fill: "forwards"
});

// 4. When the fade-out is finished, animate the new slide in
slideFadeOut.onfinish = function () {
    slides.forEach(function (slide) { 
      slide.classList.remove("active"); 
    });
    
    var activeSlide = slides[activeIndex];
    activeSlide.classList.add("active");
    
    activeSlide.animate([
        { transform: "translateX(-5%)", opacity: 0 },
        { transform: "translateX(0)", opacity: 1 }
    ], { 
        duration: 600, 
        easing: "ease-out", 
        fill: "forwards" 
    });
};
  • We first update the .active class on the nav links to give the user immediate visual feedback.
  • We use the .animate() method. It takes two arguments: an array of keyframes (the start and end states of the animation) and an options object (like duration and easing).
  • The fill: "forwards" option is important—it tells the browser to keep the styles of the final keyframe after the animation finishes.
  • We use the .onfinish event to create a sequence. The new slide only starts animating after the old one has completely faded out. This prevents them from overlapping awkwardly.

For a great beginner’s guide on manipulating the DOM, you can check out our article on Introduction to JavaScript DOM Manipulation.

Step 5: Animating the Overlays

Finally, let’s add the colorful overlay wipe. This animation runs at the same time as the slide transition to create a polished effect.

JavaScript

// ...inside the click event listener, after the slide animation logic

maxZIndex += 1; // Increment z-index to ensure the new overlay is on top

var activeOverlay = overlays[activeIndex];
activeOverlay.style.zIndex = maxZIndex;

activeOverlay.animate(
  [{ transform: "scaleX(0)" }, { transform: "scaleX(1)" }], 
  { 
    duration: 1200, 
    fill: "forwards", 
    easing: easeInOutQuart 
  }
);

Here, we animate the transform: scaleX() property from 0 (invisible) to 1 (fully visible). Because we set transform-origin: left in our CSS, this creates a smooth wipe effect from left to right. We also update the z-index to make sure the newest overlay always appears on top of the previous ones.


The Complete Code

Here is all the code put together so you can easily copy and paste it into your own project files.

HTML

HTML

<div class="carousel">
  <div class="slides">
    <img src="https://webdevservices.in/cdn/1.png" alt="Stainless Steel" />
    <img src="https://webdevservices.in/cdn/2.png" alt="Army Green" />
    <img src="https://webdevservices.in/cdn/3.png" alt="Cranberry" />
    <img src="https://webdevservices.in/cdn/4.png" alt="Midnight Blue" />
  </div>
  <div class="overlays">
    <div class="bar" style="--bar-color: #bdc3c7;"></div>
    <div class="bar" style="--bar-color: #218c74;"></div>
    <div class="bar" style="--bar-color: #dd6b7b;"></div>
    <div class="bar" style="--bar-color: #30465c;"></div>
  </div>
  <ul class="nav-links">
    <li><a href="#" class="nav-link">Stainless Steel</a></li>
    <li><a href="#" class="nav-link">Army Green</a></li>
    <li><a href="#" class="nav-link">Cranberry</a></li>
    <li><a href="#" class="nav-link">Midnight Blue</a></li>
  </ul>
</div>

CSS

CSS

@import url("https://fonts.googleapis.com/css?family=Lora:400,400i,700");
body {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  min-height: 100vh;
  margin: 0;
}
.carousel {
  position: relative;
  display: flex;
}
.carousel .slides {
  position: relative;
  top: -4em;
  left: 10em;
}
.carousel .slides img {
  position: absolute;
  width: 450px;
  height: 450px;
  opacity: 0;
  z-index: 999;
}
.carousel .slides img.active {
  opacity: 1;
}
.carousel .overlays {
  position: relative;
  width: 36em;
  height: 18em;
}
.carousel .overlays .bar {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: var(--bar-color);
  transform-origin: left;
}
.carousel .nav-links {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  margin: 0;
  padding: 0 0 0 6em;
  list-style-type: none;
}
.carousel .nav-links .nav-link {
  font-size: 2rem;
  font-family: Lora, serif;
  line-height: 2;
  text-decoration: none;
  color: #7f8c8d;
  transition: 0.3s;
}
.carousel .nav-links .nav-link:hover {
  color: #1c1e1f;
}
.carousel .nav-links .nav-link.active {
  color: black;
  pointer-events: none;
}

JavaScript

JavaScript

var navLinks = document.querySelectorAll(".carousel .nav-link");
var slides = document.querySelectorAll(".carousel .slides img");
var overlays = document.querySelectorAll(".carousel .bar");
var maxZIndex = navLinks.length;
var easeInOutQuart = "cubic-bezier(0.77, 0, 0.175, 1)";

slides[0].classList.add("active");
navLinks[0].classList.add("active");

navLinks.forEach(function (navLink, activeIndex) {
  overlays[activeIndex].style.zIndex = navLinks.length - activeIndex;

  navLink.addEventListener("click", function () {
    // nav-link
    navLinks.forEach(function (navLink) { return navLink.classList.remove("active"); });
    navLink.classList.add("active");

    // slide
    var currentSlide = document.querySelector(".carousel .slides img.active");
    var slideFadeOut = currentSlide.animate([
        { transform: "translateX(0)", opacity: 1 },
        { transform: "translateX(5%)", opacity: 0 }
    ], {
        duration: 600,
        easing: "ease-in",
        fill: "forwards"
    });

    slideFadeOut.onfinish = function () {
      slides.forEach(function (slide) { return slide.classList.remove("active"); });
      var activeSlide = slides[activeIndex];
      activeSlide.classList.add("active");
      activeSlide.animate([
          { transform: "translateX(-5%)", opacity: 0 },
          { transform: "translateX(0)", opacity: 1 }
      ], { duration: 600, easing: "ease-out", fill: "forwards" });
    };

    // overlay
    maxZIndex += 1;
    var activeOverlay = overlays[activeIndex];
    activeOverlay.style.zIndex = maxZIndex;
    activeOverlay.animate(
      [{ transform: "scaleX(0)" }, { transform: "scaleX(1)" }], 
      { duration: 1200, fill: "forwards", easing: easeInOutQuart }
    );
  });
});

Demo: Codepen

Conclusion

And there you have it! A fully functional, beautifully animated product carousel built from scratch. You’ve learned how to structure content with HTML, layer and style it with CSS, and orchestrate complex animations with the JavaScript Web Animations API.

This project is a perfect stepping stone. You can now try to expand it by adding arrow buttons for navigation, making it autoplay, or adapting it for a touch-screen device. Keep experimenting and building!


Did you find this tutorial helpful? Give it a share! If you have any questions or built your own version, drop a comment below. I’d love to see it!

12
0
Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *