How to create PROGRESS STEPS using HTML, CSS & JavaScript

ยท

6 min read

How to create PROGRESS STEPS using HTML, CSS & JavaScript

Hey, You awesome human ๐Ÿ‘‹,

Introduction

In this tutorial, we are going to see how we can build a Progress-Steps using HTML, CSS and JavaScript.

The progress-step is a mini-projects which can be used in a variety of the other high-level project to perform the desired visual effect. May be it transition between the different pages of the forms or transition between different pages of the projects.

Below is the Live Preview of the desired project


Setting Up the Project

For this project, we will use the VS Code. If you have not installed the Visual Studio Code yet, then click on the link below for download and installation according to your operating system specifications:

Visual Studio Code

For project setup, start by creating a new project folder in VS Code, and inside that project folder, create three empty new files of HTML (index.html), CSS (style.css) and JavaScript (script.js). The Html file is the entry point for our website and contains the HTML code. CSS contains the styling part of our web project and JavaScript contains various functionalities for proper functioning of our web app.


Analysis of the project

screely-1649315329766.png

As we can see from the screenshot above the page contains 4 numerical div surrounded by grey colored circular border which will change to blue when it's active. Between two circles we have a horizontal line again in grey color which too will change the color to blue upon transition.

When the pointer is at the left most location prev button is disabled and the when the pointer is at the right most location next button will be disabled.


Let's see the structuring part starting with HTML later we will see the CSS applied to each HTML element.


HTML

  • Get the HTML boilerplate

<!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>Document</title>
</head>
<body>

</body>
</html>

This boilerplate can be easily accessed by typing ! on the first line of the HTML file and pressing tab/enter key.

Change the title from document to Progress Steps


  • Linking CSS and JavaScript file to the markup

<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>

The defer attribute is a Boolean attribute. If the defer attribute is set, it specifies that the script is downloaded in parallel to parsing the page, and executed after the page has finished parsing. Note: The defer attribute is only for external scripts (should only be used if the src attribute is present).


  • Inside body Tag

contains the four div to represent different circles, enclosed inside progress-container. And two button for Prev and Next. All of which are enclosed inside an outer container along with required class and id name.

<div class="container">
       <div class="progress-container">
            <div class="progress" id="progress"></div>
            <div class="circle active">1</div>
            <div class="circle">2</div>
            <div class="circle">3</div>
            <div class="circle">4</div>
        </div>
        <button class="btn" id="prev" disabled>Prev</button>
        <button class="btn" id="next">Next</button>
</div>

Entire HTML file at a glance

<!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" />
        <link rel="stylesheet" href="./style.css" />
        <script src="./script.js" defer></script>
        <title>Progress Steps</title>
    </head>
    <body>
        <div class="container">
            <div class="progress-container">
                <div class="progress" id="progress"></div>
                <div class="circle active">1</div>
                <div class="circle">2</div>
                <div class="circle">3</div>
                <div class="circle">4</div>
            </div>
            <button class="btn" id="prev" disabled>Prev</button>
            <button class="btn" id="next">Next</button>
        </div>
    </body>
</html>

CSS

  • Adding required styling

    I target the element by class name in CSS and by id name in script.(mostly)
:root {
    --line-border-fill: #3498db;
    --line-border-empty: #e0e0e0;
}

html {
    box-sizing: border-box;
}

body {
    background-color: #f6f7fb;
    font-family: "cascadia code", sans-serif;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    overflow: hidden;
    margin: 0;
}

.container {
    text-align: center;
}

.progress-container {
    display: flex;
    justify-content: space-between;
    position: relative;
    margin-bottom: 30px;
    max-width: 100%;
    width: 500px;
}

.progress-container::before {
    content: "";
    background-color: var(--line-border-empty);
    position: absolute;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    height: 4px;
    width: 100%;
    z-index: -1;
}

.progress {
    background-color: var(--line-border-fill);
    position: absolute;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    height: 4px;
    width: 0%;
    z-index: -1;
    transition: 0.4s ease;
}

.circle {
    background-color: #fff;
    color: #999;
    border-radius: 50%;
    height: 30px;
    width: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 3px solid var(--line-border-empty);
    transition: 0.4s ease;
}

.circle.active {
    border-color: var(--line-border-fill);
}

.btn {
    background-color: var(--line-border-fill);
    color: #fff;
    border-radius: 6px;
    cursor: pointer;
    font-family: inherit;
    padding: 8px 30px;
    margin: 5px;
    border: none;
    font-size: 18px;
}

.btn:active {
    transform: scale(0.98);
}

.btn:focus {
    outline: none;
}

.btn:disabled {
    background-color: var(--line-border-empty);
    cursor: not-allowed;
}

That's conclude the whole styling part. Now, without any further ado, Let's jump right into JavaScript.


JavaScript

  • Target all the element with the help of id

const progress = document.getElementById("progress");
const prev = document.getElementById("prev");
const next = document.getElementById("next");
const circle = document.querySelectorAll(".circle");

  • Function to highlight circle border and line joining two consecutive circles

function update() {
    circle.forEach((circ, index) => {
        if (index < currentActive) {
            circ.classList.add("active");
        } else {
            circ.classList.remove("active");
        }
    });

    const actives = document.querySelectorAll(".active");
    progress.style.width =
        ((actives.length - 1) / (circle.length - 1)) * 100 + "%";

    if (currentActive === 1) {
        prev.disabled = true;
    } else if (currentActive === circle.length) {
        next.disabled = true;
    } else {
        prev.disabled = false;
        next.disabled = false;
    }
}

  • Adding Event Listener to Next button

next.addEventListener("click", () => {
    currentActive++;
    if (currentActive > circle.length) {
        currentActive = circle.length;
    }
    update();
});

  • Adding Event Listener to Prev button

prev.addEventListener("click", () => {
    currentActive--;
    if (currentActive < 1) {
        currentActive = 1;
    }
    update();
});

Entire JavaScript file at a glance

console.log("Progress Steps");

const progress = document.getElementById("progress");
const prev = document.getElementById("prev");
const next = document.getElementById("next");
const circle = document.querySelectorAll(".circle");

let currentActive = 1;

next.addEventListener("click", () => {
    currentActive++;
    if (currentActive > circle.length) {
        currentActive = circle.length;
    }
    update();
});

prev.addEventListener("click", () => {
    currentActive--;
    if (currentActive < 1) {
        currentActive = 1;
    }
    update();
});

function update() {
    circle.forEach((circ, index) => {
        if (index < currentActive) {
            circ.classList.add("active");
        } else {
            circ.classList.remove("active");
        }
    });

    const actives = document.querySelectorAll(".active");
    progress.style.width =
        ((actives.length - 1) / (circle.length - 1)) * 100 + "%";

    if (currentActive === 1) {
        prev.disabled = true;
    } else if (currentActive === circle.length) {
        next.disabled = true;
    } else {
        prev.disabled = false;
        next.disabled = false;
    }
}


Thank you for reading. If you have come this far, don't forget to react to this blog.


If You got stuck or confused at any part, don't hesitate to ping me in the comment section or my social handles.


If you โค๏ธ My Content! Connect with me on Twitter (abhinav_jha07)


Show your support by buying me a coffee

Buy Me A Coffee


My other digital presence:


More Content at abhinavjha07.hashnode.dev/


Your feedback is more than welcome

Did you find this article valuable?

Support Abhinav's Blog by becoming a sponsor. Any amount is appreciated!

ย