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 transformleftBtnandrightBtn— the buttons that will receive click event listenersimgsAll— a collection of allimgelements 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
imgelements inside the element with the idimgs. - 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
idxwithin valid bounds - update the transform so the correct image is shown
Keeping idx within range
imgsAll.length - 1gives 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.