Building an Image Carousel with JavaScript

Overview

This carousel works by keeping track of the current slide with idx. Every 2 seconds, run() increases idx and calls changeImage(). The changeImage() function makes sure the index stays within range, then moves the image container horizontally with translateX(). The button listeners also change idx, update the UI, and restart the interval so manual interaction does not conflict awkwardly with auto-sliding.

Selecting the elements

First, we select elements and store them in variables. Next, we attach behavior to them.

  • imgs — the image container that will be moved horizontally with transform
  • leftBtn and rightBtn — the buttons that will receive click event listeners
  • imgsAll — a collection of all img elements inside #imgs

Since .querySelectorAll() is used, imgsAll is a NodeList, not a true array. However, it is similar to an array in important ways: each item has an index, and the .length property is available.

The callback function does not run immediately when JavaScript reads the file. It gets registered and runs later when the event happens.

In other words, the browser is essentially storing:

“When this element is clicked, run this function.”

Timed behavior

setInterval(run, 2000)

  • Every 2000 milliseconds, call run again.
  • Here, we are passing the function reference, not calling it immediately.
  • This is what creates the repeated auto-slide behavior.

Selecting all images

const imgsAll = document.querySelectorAll('#imgs img')

  • This finds all img elements inside the element with the id imgs.
  • If there were other elements inside #imgs, they would not be included.
  • Because there is a space and not a >, this selector matches any img descendant inside #imgs, not only direct children.

State

let idx = 0

  • idx is a variable chosen to represent the current image position.
  • It means: “Start by treating image 0 as the active image.”

changeImage()

The changeImage() function has two jobs:

  • keep idx within valid bounds
  • update the transform so the correct image is shown

Keeping idx within range

  • imgsAll.length - 1 gives the last valid index in the NodeList
  • if (idx > imgsAll.length - 1) means we moved past the last image, so reset to the first image
  • else if (idx < 0) means we moved backward past the first image, so wrap around to the last image

Updating the UI

imgs.style.transform = translateX(${-idx * 500}px)

This moves the image container horizontally so the correct image is visible.

At first, I thought there might need to be an additional else before this line, but there does not. The transform should happen every time, no matter what. It is the final UI update, so it belongs outside the if / else if.

The buttons

Event listeners are attached to the right and left button elements.

Their callbacks handle:

  • moving to the next or previous image by incrementing or decrementing idx
  • updating the UI by calling changeImage()
  • restarting the timer by calling resetInterval()

Why resetInterval() matters

Without resetInterval(), the old timer would keep counting from wherever it already was. That means if the user clicked manually right before the next automatic slide, the carousel could move again almost immediately.

Resetting the interval makes the timing feel more natural.

From MDN:

The clearInterval() method of the Window interface cancels a timed, repeating action previously established by a call to setInterval(). If the parameter provided does not identify a previously established action, this method does nothing.