Building a Carousel with Vanilla JavaScript

Last Updated : 18 Mar, 2026

A carousel is a common UI component that lets users cycle through images or content slides interactively. Building one with vanilla JavaScript helps you understand core DOM manipulation and event handling without relying on libraries.

  • Create a container with slides and navigation buttons (next/prev).
  • Use JavaScript to track the current slide index and update the view.
  • Add smooth transitions for a better user experience.

Approach

  • Basic Carousel: Use HTML to structure the images and CSS for layout and responsiveness.
  • Navigation Buttons: Add "Previous" and "Next" buttons to manually move through images.
  • Auto Play: Implement JavaScript to automatically cycle through images at intervals.
  • Styling: Use CSS to enhance the appearance with borders, shadows, transitions, and ensure responsiveness.

Project Preview

The first step in building a carousel is to define its HTML & CSS structure. We'll need a container for the carousel, individual images, and navigation buttons for the user to move between the images.

HTML
<html>
<head>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: #f4f4f4;
        }
        .car {
            position: relative;
            width: 80%;
            max-width: 600px;
            overflow: hidden;
        }
        .img-wrap {
            display: flex;
            transition: transform 0.5s ease;
        }
        .img-wrap img {
            width: 100%;
            height: auto;
        }
        .btn {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background: rgba(0, 0, 0, 0.5);
            color: #fff;
            border: none;
            padding: 10px;
            font-size: 16px;
            cursor: pointer;
        }
        .btn:hover {
            background: rgba(0, 0, 0, 0.8);
        }
        .prev {
            left: 10px;
        }
        .next {
            right: 10px;
        }
    </style>
</head>
<body>
    <div class="car">
        <div class="img-wrap">
            <img src="https://media.geeksforgeeks.org/wp-content/uploads/20241228102812942963/0_ilw552fVUGbwIzbE.jpg"
                alt="1">
            <img src="https://media.geeksforgeeks.org/wp-content/uploads/20241128161121752603/what-is-javascript.webp"
                alt="2">
            <img src="https://media.geeksforgeeks.org/wp-content/uploads/20240829155421/Amazing-new-Javascript-features-in-ES15.webp"
                alt="3">
        </div>
        <button class="btn prev"></button>
        <button class="btn next"></button>
    </div>
</body>
</html>
  • Body: Center content both vertically and horizontally, with a light background and no margin/padding.
  • Carousel: Restrict width to 80% with a max of 600px, and hide any overflow.
  • Image Wrapper: Arrange images in a row using flex, with smooth transition on transformation.
  • Images: Set images to take full width, keeping their aspect ratio intact.
  • Buttons: Position buttons (prev/next) in the center vertically, with semi-transparent background.
  • Button Hover: Darken button background on hover for better visibility.
  • Prev Button: Position the previous button to the left.
  • Next Button: Position the next button to the right.

we add the functionality for navigating between images, as well as autoplay that switches the images automatically.

JavaScript
const prev = document.querySelector('.prev');
const next = document.querySelector('.next');
const wrap = document.querySelector('.img-wrap');
const imgs = document.querySelectorAll('.img-wrap img');

let idx = 0;

function showImg() {
    if (idx >= imgs.length) idx = 0;
    if (idx < 0) idx = imgs.length - 1;
    wrap.style.transform = `translateX(-${idx * 100}%)`;
}

next.addEventListener('click', () => {
    idx++;
    showImg();
});

prev.addEventListener('click', () => {
    idx--;
    showImg();
});

setInterval(() => {
    idx++;
    showImg();
}, 3000);

showImg();
  • prev and next buttons for navigation are selected using querySelector.
  • wrap refers to the container for the images.
  • imgs holds all the individual images inside the wrap.
  • idx is a variable to keep track of the currently displayed image.
  • If idx is greater than or equal to the number of images, reset it to 0.
  • If idx is less than 0, reset it to the last image index.
  • Moves the wrap by updating its transform style to shift images horizontally based on the current idx.
  • Next Button: Increments idx and calls showImg() to display the next image.
  • Previous Button: Decrements idx and calls showImg() to display the previous image.
  • Uses setInterval to increment idx every 3000ms (3 seconds) and updates the displayed image via showImg().

Complete Code

HTML
<html>
<head>
    <title>Vanilla JavaScript Carousel</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: #f4f4f4;
        }
        .car {
            position: relative;
            width: 80%;
            max-width: 600px;
            overflow: hidden;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }
        .img-wrap {
            display: flex;
            transition: transform 0.5s ease;
        }

        .img-wrap img {
            width: 100%;
            height: auto;
            flex-shrink: 0;
        }
        .btn {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background: rgba(0, 0, 0, 0.5);
            color: #fff;
            border: none;
            padding: 10px;
            font-size: 16px;
            cursor: pointer;
            border-radius: 50%;
        }

        .btn:hover {
            background: rgba(0, 0, 0, 0.8);
        }

        .prev {
            left: 10px;
        }

        .next {
            right: 10px;
        }
    </style>
</head>
<body>
    <div class="car">
        <div class="img-wrap">
            <img src="https://media.geeksforgeeks.org/wp-content/uploads/20241228102812942963/0_ilw552fVUGbwIzbE.jpg" alt="Image 1">
            <img src="https://media.geeksforgeeks.org/wp-content/uploads/20241128161121752603/what-is-javascript.webp" alt="Image 2">
            <img src="https://media.geeksforgeeks.org/wp-content/uploads/20240829155421/Amazing-new-Javascript-features-in-ES15.webp" alt="Image 3">
        </div>
        <button class="btn prev"></button>
        <button class="btn next"></button>
    </div>
    <script>
        const prev = document.querySelector('.prev');
        const next = document.querySelector('.next');
        const wrap = document.querySelector('.img-wrap');
        const imgs = document.querySelectorAll('.img-wrap img');
        let idx = 0;
        function showImg() {
            if (idx >= imgs.length) idx = 0;
            if (idx < 0) idx = imgs.length - 1;
            wrap.style.transform = `translateX(-${idx * 100}%)`;
        }
        next.addEventListener('click', () => {
            idx++;
            showImg();
        });

        prev.addEventListener('click', () => {
            idx--;
            showImg();
        });
        setInterval(() => {
            idx++;
            showImg();
        }, 3000);
        showImg();
    </script>
</body>
</html>
Comment