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:
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
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 byclass
name inCSS
and byid
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
andline
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
toNext
button
next.addEventListener("click", () => {
currentActive++;
if (currentActive > circle.length) {
currentActive = circle.length;
}
update();
});
Adding
Event Listener
toPrev
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
My other digital presence:
Mail: x3vgi9xr@duck.com
GitHub: akj0712
LinkedIn: abhinavjha07
Telegram: abhinav_kumar_jha
More Content at abhinavjha07.hashnode.dev/
Your feedback is more than welcome