How to Create a Reusable Slider using HTML, CSS, and JavaScript

Within the software community, Slider has grown to be highly regarded. You barely ever use a web or mobile application today without dealing with a slider. Sliders are now commonly used on social media platforms to display a variety of media, including text, videos, and even images.

The creation of numerous libraries to address the issue has made adding a slider to a web application easier. However, using a library to create a basic slider or carousel for a web application might be complex because it includes many more functionalities that might not be required.

I'll walk you through each step of creating a slider in this tutorial using only HTML, CSS, and Javascript. Additionally, this course will help you comprehend how these sliders normally operate and provide you with a fundamental understanding of how those libraries function. Let's get right to work on adding a slider or swiper.

Setting up the HTML structure for the slider

Writing the markup in our code editor is the first step in setting up our slider. If you haven't already, now is the moment to launch your code editor. Create a index.html file in your code editor and paste the following code into it.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JS Slider</title>
</head>

<body>
    <section>
        <div class="slider">
            <div class="slide slide-1">
                <h1>Hello Slide 1</h1>
            </div>
            <div class="slide slide-2">
                <h1>Hello Slide 2</h1>
            </div>
            <div class="slide slide-3">
                <h1>Hello Slide 3</h1>
            </div>
            <div class="slide slide-4">
                <h1>Hello Slide 4</h1>
            </div>
        </div>
    </section>
</body>

</html>

Hint: If you are using VSCode, you can type "!" and press enter to create a boilerplate code for HTML

We'll start by examining the code above. The container for the slider will be the <section>tag, which is where the <div class="slider"> tag resides. The container contains embedded copies of our slides. Each slide must be assigned an attribute of class="slide" as this will help us identify each of our slides when we start developing the javascript. The additional attribute is optional because we only use it to modify the slide's structure.

Styling the slider with CSS

To begin styling, create a new file called slider.css or any other name of your choice. This file will contain all of the stylings for our slider. As shown below, we will link our stylesheet to our HTML code by including the <link> tag in the <head> of our HTML.

 <link rel="stylesheet" href="slider.css">

Next, we'll set the layout of our page. To do this, we'll style the <section> so that it fills the entire screen and remove any instances of overflowing.

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

html {
    font-family: 'Montserrat', sans-serif;
    font-size: 20px;
    background: white;
}
section {
    height: 100vh;
    width: 100%;
}

Our page now appears to be fully prepared for the implementation of our slider.

For the slider, we will select the slider container and set it to cover 100% of the available space, which will be determined by the parent element that houses it.

The slider and slide class styles are provided below.

.slider {
    height: 100%;
    width: 100%;
}

.slide {
    height: 100%;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    background-size: cover;
    transform: translateX(100%);
}

.slide::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    z-index: -1;
    background-color: rgba(0, 0, 0, 0.2);
}

For each of the slides, set the height and width to occupy the size of the container. Using the flexbox model, we position all the elements in the slide to stay at the center of the slide. We also set position: absolute; so that it is positioned relative to the nearest-positioned ancestor.

The background-size property is set to cover so that when an image is added to the background of the slide, it is set to cover the whole dimensions of the slide itself.

The next important thing is the transform: translateX(100%); the translate property in CSS allows you to transfer an element from one place to another along the X (horizontal) axis, the Y (vertical) axis, and the Z (depth) axis. This allows us to position each slide away from the device's screen or on the screen.

From the embedded codesandbox above, you will realize we have our slides overlapping each other, which is due to the position being set to absolute. We'll remove the comment from the transform to send all slides away from the screen, and we'll add a new class to the first slide.

<section>
    <div class="slider">
        <div class="slide active slide-1">
            <h1>Hello Slide 1</h1>
        </div>
        <div class="slide slide-2">
            <h1>Hello Slide 2</h1>
        </div>
        <div class="slide slide-3">
            <h1>Hello Slide 3</h1>
        </div>
        <div class="slide slide-4">
            <h1>Hello Slide 4</h1>
        </div>
    </div>
</section>
.slide.active {
    transform: translateX(0);
    z-index: 1;
}

Our first slide is currently the only one visible on the window. The other slides will overlap each other as you move your scroll bar along the x-axis. We will add overflow-x and position:relative; to our section styling to get rid of the horizontal scroll bar.

section {
    height: 100vh;
    overflow-x: hidden;
    position: relative;
    width: 100%;
}

Adding next and previous buttons

Our slider is gradually building up, and for this section, we will be adding the buttons that will serve the purpose of getting us to the next or previous slide. Let's get back to writing codes.

<div class="buttons">
    <div class="next"><ion-icon name="chevron-forward-outline"></ion-icon></div>
    <div class="prev"><ion-icon name="chevron-back-outline"></ion-icon></div>
</div>

This is the markup for our buttons. We will be using ionicons for our icons. Ionicons is a completely open-source icon set with 1,300 icons crafted for web, iOS, Android, and desktop apps. We will be linking it inside a <script> which will be placed at the bottom of our HTML just before the closing </body>. To learn more about ionicons, click here.

<script type="module" src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.esm.js"></script>

For the purpose of styling, we will position our buttons in the middle of the screen, with each button pointing to the subsequent or preceding slide.

.buttons {
    position: absolute;
    width: 95%;
    bottom: 50%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-direction: row-reverse;
    z-index: 5;
    color: black;
}

.buttons div {
    width: 50px;
    height: 50px;
    font-size: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    pointer-events: all;
    transition: all 0.5s ease-in-out;
}

.buttons div:hover {
    background-color: white;
}

The codesandbox below represents the current state of our slider.

Completing the UI

For the final section of our UI, we will be adding the dots that will enable the user to know the total number of slides we have in our slider and let the user click on a dot to go to the slide at that index. Add the following code below under the buttons (next and previous) section.

<div class="dots"></div>

The styling for our dots can be found below as well.

.dots {
    position: absolute;
    bottom: 10%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    z-index: 5;
}

.dots .dot {
    display: inline-block;
    height: 10px;
    width: 10px;
    background-color: rgba(0, 0, 0, 0.4);
    border-radius: 10px;
    margin: 10px;
    z-index: 5;
    cursor: pointer;
    transition: 0.4s ease width;
}

.dots .dot.active {
    background-color: black;
    width: 30px;
}

Implementing slider functionality with JavaScript

To get started with the JavaScript implementation, make a new file called slider.js to serve as the connector between our HTML code and our JavaScript file.

<script src="slider.js"></script> <!-- adding this script to your index.html -->

We will use the querySelector() to select all our slides, buttons, and dots as shown below.

const slides = Array.from(document.querySelectorAll('.slide')); // Array.from() converts a NodeList to an Array
const slider = document.querySelector('.slider');
const buttons = document.querySelectorAll('.buttons div');
const dotEl = document.querySelector('.dots');

Instead of merely picking them as nodelists, we want to organize our slides into an array so that we can navigate through it to find the next, previous, and current slide.

The getNextPrev() function

const getNextPrev = () => {
    const activeSlide = document.querySelector('.slide.active');
    const activeIndex = slides.indexOf(activeSlide);
    const allSlidesCount = slides.length;

    let nextSlide, prevSlide;

    if (allSlidesCount <= 2) {
        if (activeIndex === 0) {
            nextSlide = slides[1];
            prevSlide = slides[1];
            prevSlide.classList.remove('animate');
        } else {
            nextSlide = slides[0];
            prevSlide = slides[0];
            prevSlide.classList.remove('animate');
        }
    } else {
        nextSlide = slides[activeIndex + 1];
        prevSlide = slides[activeIndex - 1];
    }

    if (nextSlide === undefined) {
        nextSlide = slides[0];
    }

    if (prevSlide === undefined) {
        prevSlide = slides[slides.length - 1];
    }

    return [nextSlide, prevSlide];
};

This function will be responsible for getting the next and previous slide ready for use at any point in time when the user clicks on either the next or previous button. In this function, we get the active slide and index of the active slide by targeting the slide with the active class. If the total number of our slides is less than three, we reset the index of either the next or previous slide to ensure that our slider does not malfunction.

We add the index of our current slide by 1 and set it to our nextSlide variable using the slides array we first constructed. We do the same for the prevSlide but this time, we subtract 1.

If this is completed, we return our nextSlide and prevSlide in the form of an array so that the other functions can access it.

The getPosition() function

const getPosition = () => {
    const activeSlide = document.querySelector('.slide.active');
    const activeIndex = slides.indexOf(activeSlide);
    const nextPrev = getNextPrev();
    const nextSlide = nextPrev[0];
    const prevSlide = nextPrev[1];

    slides.forEach((slide, index) => {
        if (index === activeIndex) {
            slide.style.transform = 'translateX(0)';
        } else if (slide === prevSlide) {
            slide.style.transform = 'translateX(-100%)'; // move the previous slide to the left out of the window
        } else if (slide === nextSlide) {
            slide.style.transform = 'translateX(100%)'; // move the next slide to the right out of the window
        } else {
            slide.style.transform = 'translateX(100%)';
        }

        slide.addEventListener('transitionend', () => {
            slide.classList.remove('animate');
        });
    });
};

A slide is positioned in or out of the viewport using the getPosition() function. We briefly go through the CSS translate above. We added a new class of animate to our slide to give us a smooth transition of slides in and out of the screen by using the JavaScript translateX property to set the next slide right out of the viewport and the previous slide left out of the viewport.

/* the animate class styling added to our slide class */
.animate {
    transition: transform 0.5s ease-in-out;
    z-index: 5;
}

The getNextSlide() and getPrevSlide() functions

const getNextSlide = () => {
    const activeSlide = document.querySelector('.slide.active');
    const nextPrev = getNextPrev();
    const nextSlide = nextPrev[0];

    if (activeSlide.classList.contains('animate')) return;
    activeSlide.classList.add('animate'); // add the animate class in other to add the transition effect to slides
    nextSlide.classList.add('animate');
    activeSlide.classList.remove('active');
    nextSlide.classList.add('active');

    getPosition();
};

const getPrevSlide = () => {
    const activeSlide = document.querySelector('.slide.active');
    const nextPrev = getNextPrev();
    const prevSlide = nextPrev[1];

    if (activeSlide.classList.contains('animate')) return;
    activeSlide.classList.add('animate');
    prevSlide.classList.add('animate');
    activeSlide.classList.remove('active');
    prevSlide.classList.add('active');

    getPosition();
};

getPosition(); // Initiate the slider

We can create a slider with the minimal functionality we need by using the getNextSlide() and getPrevSlide() functions.

We will be able to transition between slides quickly and easily.

Based on user interaction with arrow buttons, both routines obtain the active slide, remove the active class from it, and add it to the subsequent or preceding slide.

Creating an automatic slideshow (autoplay) with JavaScript

The entire concept of slides navigating automatically on a website without user interaction is due to repeatedly running a function after a specific time interval.

To implement this function in our code, we will create a new JavaScript function inside our slider.js

const autoPlay = () => {
    setInterval(() => {
        getNextSlide();
    }, 5000);
};

// function below checks if slider contains the autoplay class to initiate the slide
if (slider.classList.contains('autoplay')) {
    autoPlay();
}

We added a conditional statement to check if our slider container has an extra class autoplay, which will initialize the autoplay functionality. Now our slides will be changed every 5 seconds, automatically.

Adding the dots and their functionality

In sliders, we frequently see dots that display the number of slides, the current slide index, and allow the user to click on a dot to navigate to the slide at that index. We have added the HTML code of the dots already and the styling, we will move to implementing the functionalities I outline above.

// add the dots to the slider
slides.forEach((slide) => {
    const dot = document.createElement('div');
    dot.classList.add('dot');
    dotEl.appendChild(dot);
});

// this function will get the active dot and add the active class to it
const getActiveDot = () => {
    const allDots = document.querySelectorAll('.dots .dot');
    const activeSlide = document.querySelector('.slide.active');
    const activeIndex = slides.indexOf(activeSlide);

    allDots.forEach((dot) => {
        dot.classList.remove('active');
    });

    allDots[activeIndex].classList.add('active');
    allDots.forEach((dot, index) => {
        dot.addEventListener('click', () => {
            moveToDot(index);
        });
    });
};

// this function will move the slider to the dot that was clicked
const moveToDot = (index) => {
    slides.forEach((slide) => {
        slide.classList.remove('active');
    });

    slides[index].classList.add('active');
    getPosition();
    getActiveDot();
};

moveToDot(0);
getActiveDot();

The code above is divided into three different sections, which will be explained below.

  1. Adding the dots to the slider - This section targets the dots class we created in our HTML code, using DOM manipulation, we append the dots container with the number of slides as dot.

  2. The getActiveDot() function - The function gets all the dots from our HTML and gets the active slide. It will first check if any dot has the active and remove it after looping through using the forEach() function. Using the current slide index, it adds the active class to the dot at the same index as the slide.

  3. The moveToDot() function - This function simply checks for which dot was clicked and then moves the active class of the slide to the index as the dot.

Finally, we want to class the getActiveDot() function in our getNextSlide() and getPrevSlide()

const getPrevSlide = () => {
    // ...
    getActiveDot()
}

const getNextSlide = () => {
    // ...
    getActiveDot()
}

Adding touch and swipe support for mobile devices

The most popular means of internet access are mobile devices. The experience of using a website feature that is incompatible with mobile devices will be quite terrifying for your users. Thanks to javascript methods that make this procedure easier for us, we will be able to implement the swipe capability for our slider with just a few lines of code.

let startX;
const handleTouchStart = (e) => {
    startX = e.touches[0].clientX;
};

const handleTouchEnd = (e) => {
    const endX = e.changedTouches[0].clientX;
    const deltaX = endX - startX; // this will give us the distance between the start and end of the touch

    if (deltaX > 50) {
        getPrevSlide();
    } else if (deltaX < -50) {
        getNextSlide();
    }
};

slider.addEventListener('touchstart', handleTouchStart, false);
slider.addEventListener('touchend', handleTouchEnd, false);

To add the swipe functionality, we create a variable startX that will store the x-axis value of our user's interaction with the screen. Create a new function handleTouchStart() that will be in charge of determining the value of startX based on the user's touches on the x-axis.

To calculate the user's touch from beginning to end, create the handleTouchEnd() function. This function will save the value of the user's movement on the x-axis in deltaX.

The function will also determine whether the deltaX is positive or negative, and if it is positive, it will call the subsequent slide; if it is negative, it will call the previous slide.

Finally, we will use Javascript event listeners to listen for when the user first touches the screen and call handleTouchStart(), as well as listen for when the user stops the initial touch and call handleTouchEnd().

Conclusion

In conclusion, using HTML, CSS, and JavaScript to create a slider is a useful way to include a dynamic element on a website. The page's structure and layout are provided by HTML, its styling and formatting are provided by CSS, and its functionality and interactivity are provided by JavaScript. Your website visitors will be engaged by a sleek, dynamic slider created using just these three technologies. You can view the full code of the slider here and also the live demo can be accessed here.

1
Subscribe to my newsletter

Read articles from ISAH ABBA IBRAHIM directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ISAH ABBA IBRAHIM
ISAH ABBA IBRAHIM