An image slider web application

Muhammad Saqib Ilyas
9 min readDec 27, 2023

--

An image slider is one of the projects that are prescribed practice for new frontend developers. Let’s build one in this article.

Initially, an image will be displayed on our web page, with a “Next”, and a “Previous” button below it. Clicking the “Next” button will make the currently displayed image slide appear to slide away and disappear towards the left, while another image appears to slide from left to right. A similar but opposite effect is expected on the “Previous” button.

The starter HTML

Here’s the HTML structure:

<!DOCTYPE html>
<html>
<head>
<title>Image slider</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="fontawesome/css/all.min.css">
</head>
<body>
<h2>An image slider</h2>
<section class="centered">
<div id="slider"></div>
<div class="btn-bar">
<button id="previous">
<i class="fas fa-backward"></i>
</button>
<button id="next">
<i class="fas fa-forward"></i>
</button>
</div>
</section>
<script src="app.js"></script>
</body>
</html>

In the head element, we link to our stylesheet which we’ll write in a moment. We link to the fontawesome stylesheet as well. I assume that we’ve downloaded and placed the fontawesome distribution in the project directory.

In the body element, we have a heading, followed by a section element, where all the action happens. It has a class of centered, as that is how we want it to appear. It contains a div element, with an id of slider, in which we will show our images. It also has a div element with a class of btn-bar which holds two button elements. We’re using fontawesome icons for the “Next” and “Previous” buttons. The button elements are assigned unique ids so we can access and associate event handlers to them in JavaScript. Towards the end, we link to our app.js file in a script tag.

The images

I downloaded 5 free images from unsplash using the unsplash image downloader Chrome extension so that they are all of equal size. I put them in an imgs subdirectory in the project directory.

The CSS

Here’s the CSS that we start with:

*, ::before, ::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}

body {
background: rgba(0, 0, 0, 0.15);
}

h2 {
text-align: center;
margin: 10px 0;
}

.centered {
margin: 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 600px;
}

#slider {
width: 600px;
height: 400px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
display: flex;
}

#slider img {
width: 100%;
transition: transform 1s ease;
}

.centered .btn-bar {
display: flex;
width: 50%;
justify-content: space-evenly;
margin: 10px 0;
}

We start with a CSS reset to get rid of some browser-specific settings for a perdictable layout. We give the page a grayish background color. We center align the h2 heading. We also give it a bit of spacing above and below, so that it isn’t too close to the window’s top edge and sufficiently spaced from the content below it.

We horizontally center our section element with the margin: 0 auto; directive. To control the layout of the images and the buttons in separate rows, we choose CSS Flexbox, and set its flex-direction property to column. To center the contents of this section vertically as well as horizontally by setting the align-items and justify-content properties to center. We give the section a width of 600 pixels which should be enough for our images. We’ll let the content dictate this element’s height.

When I displayed an image with a width of 600 pixels, its height was 400 pixels. So, on the slider element, I set a height of 400 pixels and a width of 600 pixels. I gave a box shadow to create a 3D effect. To arrange the images inside this container, I set its display property to flex.

Then, I set the img elements to have a width equal to 100% of the slider container. I also applied a transition effect of a one second duration on the images. We’ll set the actual transform later.

To arrange the buttons, I selected the btn-bar class and picked Flexbox for its layout. I set it to half the width of its container, because having the buttons near the center of the display makes more sense. I configure Flexbox to space the buttons evently within this width, and gave the buttons a bit of margin on the top and bottom to space the buttons away from the images above them.

Displaying the images

We haven’t inserted the images, yet. Let’s do that using JavaScript. We’ll create img elements for each image, and append it to the slider element. I named my images pic1.jpg, pic2.jpg, pic3.jpg, pic4.jpg, and pic5.jpg.

const numImages = 5

const sliderElement = document.getElementById('slider')

loadImages()

function loadImages() {
for (let i = 1 ; i <= numImages ; i++) {
const imgElement = document.createElement('img')
imgElement.src = `imgs/pic${i}.jpg`
sliderElement.appendChild(imgElement)
}
}

We initialize a variable to the total number of images. We acquire an object representing the slider element so that we can add the images to it. We run a for loop 5 times. Each time through the loop, we create an img element using the document.createElement() method. We set the src attribute of the img element to an image’s path using a template literal string. In the first iteration of the for loop, the value of i is 1, so that template literal string equals imgs/pic1.jpg which is the relative path of the first image. Similarly, all img elements are created and appended to the slider element using the appendChild() method. Since we’ve called the loadImages() function, this creates the following markup:

<div id="slider">
<img src="imgs/pic1.jpg">
<img src="imgs/pic2.jpg">
<img src="imgs/pic3.jpg">
<img src="imgs/pic4.jpg">
<img src="imgs/pic5.jpg">
</div>

At this point, you should see all five images displayed side by side inside the slider element.

Images displayed side by side

Of course, that’s not what we want. We want only one image displayed. But we’ll fix that shortly. Right now, it helps to be able to see all the images the way they are. If you just set overflow: hidden; on the slider element, you’ll see just one image like this:

Setting overflow to hidden shows just the first image

But, don’t save that setting just yet. Like I said, it helps to see all the images for the sliding effect.

The sliding effect in JavaScript

Now, let’s implement the sliding effect on the images. First, let’s think what we need to do to slide to the next image. The first image is already displayed at the center. To get the second image at the center, we could shift all of the images to the left. That is a translateX() transform by an amount of -100%. Think of a band on which the five images are stuck, and you slid the band to the left. What does it take to display the third image? A translateX(-200%) on all the images. So on and so forth.

The following image shows what it takes to display a given image number.

To display a particular image, all the images must be shifted by a certain amount

With an x translation of 0%, image number 1 is in the center frame. To display image number 2, all images must be x translated by -100%, and so on. In general, to display image number i, all the images must be x translated by (i-1)*100%.

It’s implementation time.

let imageNumber = 1
const numImages = 5

const sliderElement = document.getElementById('slider')
const nextButton = document.getElementById('next')
let images

nextButton.addEventListener('click', nextImage)

loadImages()

function loadImages() {
for (let i = 1 ; i <= numImages ; i++) {
const imgElement = document.createElement('img')
imgElement.src = `imgs/pic${i}.jpg`
sliderElement.appendChild(imgElement)
}
images = document.querySelectorAll('#slider img')
}

function showSlide() {
images.forEach( img => {
img.style.transform = `translateX(-${(imageNumber - 1) * 100}%)`
})
}

function nextImage() {
if (imageNumber < numImages) {
imageNumber++
}
else {
imageNumber = 1
}
showSlide()
}

We add a variable to hold the currently displayed image’s number. Another thing that we do is to add a line to the loadImages() function which obtains an object referencing all the img elements that are inside the slider element. This collection is stored in the images variable.

We acquire objects referencing the “Next” button. We hook up a click event handler on the “Next” button. In that event handler, we increment the current image number as long as its present value is less than 5. If it is already at 5, we reset it to 1 (we loop around to image number 1). Once we’ve updated the current image number, we call a showSlide() function. That function iterates over the images variable, and updates the transform property on all the images one by one according to the formula that we discussed earlier.

Now, if you click on the “Next” button, you’ll see the images slide to the left, until you reach the last image. If you hit the left button again, the images will slide to the right until the first image is back in view. You’ll still see all the images. To see one image at a time, modify the style specification for the slider element to the following:

#slider {
width: 600px;
height: 400px;
overflow: hidden;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
display: flex;
}

Now, you should see one image at a time, and be able to slide to the next image. Implementing the previous image scrolling is just a matter of adding a few lines of code to JavaScript:

let imageNumber = 1
const numImages = 5

const sliderElement = document.getElementById('slider')
const nextButton = document.getElementById('next')
const prevButton = document.getElementById('previous')
let images

nextButton.addEventListener('click', nextImage)
prevButton.addEventListener('click', previousImage)

loadImages()

function loadImages() {
for (let i = 1 ; i <= numImages ; i++) {
const imgElement = document.createElement('img')
imgElement.src = `imgs/pic${i}.jpg`
sliderElement.appendChild(imgElement)
}
images = document.querySelectorAll('#slider img')
}

function showSlide() {
images.forEach( img => {
img.style.transform = `translateX(-${(imageNumber - 1) * 100}%)`
})
}

function nextImage() {
if (imageNumber < numImages) {
imageNumber++
}
else {
imageNumber = 1
}
showSlide()
}

function previousImage() {
if (imageNumber > 1) {
imageNumber--
}
else {
imageNumber = 5
}
showSlide()
}

We acquired an object referencing the “Previous” button. We hooked up a click event handler to it, which is very similar to that for the “Next” button, except we’re decrementing the current image number. If it reaches 1, we wrap it around to 5.

That’s all folks!

That concludes our project. You may download the entire source code along with 5 free images from this github repository. If you prefer copy-paste, here’s the HTML:

<!DOCTYPE html>
<html>
<head>
<title>Image slider</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="fontawesome/css/all.min.css">
</head>
<body>
<h2>An image slider</h2>
<section class="centered">
<div id="slider"></div>
<div class="btn-bar">
<button id="previous">
<i class="fas fa-backward"></i>
</button>
<button id="next">
<i class="fas fa-forward"></i>
</button>
</div>
</section>
<script src="app.js"></script>
</body>
</html>

Here’s the CSS:

*, ::before, ::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}

body {
background: rgba(0, 0, 0, 0.15);
}

h2 {
text-align: center;
margin: 10px 0;
}
.centered {
margin: 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 600px;
}

#slider {
width: 600px;
height: 400px;
overflow: hidden;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
display: flex;
}

#slider img {
width: 100%;
transition: transform 1s ease;
}

.centered .btn-bar {
display: flex;
width: 50%;
justify-content: space-evenly;
margin: 10px 0;
}

and here’s the JavaScript:

let imageNumber = 1
const numImages = 5

const sliderElement = document.getElementById('slider')
const nextButton = document.getElementById('next')
const prevButton = document.getElementById('previous')
let images

nextButton.addEventListener('click', nextImage)
prevButton.addEventListener('click', previousImage)

loadImages()

function loadImages() {
for (let i = 1 ; i <= numImages ; i++) {
const imgElement = document.createElement('img')
imgElement.src = `imgs/pic${i}.jpg`
sliderElement.appendChild(imgElement)
}
images = document.querySelectorAll('#slider img')
}

function showSlide() {
images.forEach( img => {
img.style.transform = `translateX(-${(imageNumber - 1) * 100}%)`
})
}

function nextImage() {
if (imageNumber < numImages) {
imageNumber++
}
else {
imageNumber = 1
}
showSlide()
}

function previousImage() {
if (imageNumber > 1) {
imageNumber--
}
else {
imageNumber = 5
}
showSlide()
}

--

--

Muhammad Saqib Ilyas

A computer science teacher by profession. I love teaching and learning programming. I like to write about frontend development, and coding interview preparation