×

Search anything:

Progress Bar with JavaScript

Binary Tree book by OpenGenus

Open-Source Internship opportunity by OpenGenus for programmers. Apply now.

In this article, I will walk you through how I created a simple progress bar with JavaScript.

Table of contents:

  1. The prototype of Progress Bar
  2. HTML code
  3. CSS
  4. JavaScript code

The prototype of Progress Bar

progressbar
This is how the prototype looks when it's in action. It's built with HTML, CSS, and JavaScript.
By default, the progress bar is empty (it has 0% of progress) and once we click the "run progress" button, the progress runs until it reaches the end which is 100%.
I also added an input field where we can enter a number and after that, when we run the progress again, it only runs until the specific number. So like this, we can control how far the progress should run.
Let's look at the HTML structure.

HTML code

<!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>Progress Bar</title>
    <link rel="stylesheet" href="./style.css" type="text/css" />
  </head>
  <body>
    <h1>Progress Bar with JavaScript</h1>
    <div id="content">
      <div id="progress-container">
        <div id="progress-bar"></div>
      </div>
      <div id="buttons-container">
        <button id="run-progress">Run progress</button>
        <label
          >Set your progress:
          <input
            type="number"
            id="progress-number"
            placeholder="Enter a number"
          />
        </label>
      </div>
    </div>
    <script src="./index.js"></script>
  </body>
</html>

I have an index.html file that holds the structure of the progress bar.
In the head element, I added a link tag that connects the HTML file to the file called, style.css which sits in the same directory.
In the body element, I have an h1 element (the title), a div element with the id "content", and a script tag that connects the HTML file to the index.js file that is in the same directory as well.

Inside the div with the id "content", I added additional two other div elements, one with the id "progress-container" and the other with the id "buttons-container".
Now, the one with the id "progress-container", I will just call it a container. This container is the gray bar that holds our progress.
Our progress is the div with the id "progress-bar" and I will just call it the progress bar throughout this article at OpenGenus.

The buttons container holds our button which runs the progress and input with the type number.

I added the input because I wanted to add a functionality where we can somehow control the progress. I will explain this functionality below in the JavaScript section.

CSS

The styles I applied are really simple:

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

body {
  padding: 50px 25px;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30%;
}

#content {
  width: 100%;
}

#progress-container {
  width: 100%;
  height: 30px;
  margin-bottom: 25px;
  background: gainsboro;
}

#progress-bar {
  width: 0;
  height: 100%;
  background: rgb(51, 131, 252);
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  font-weight: 700;
}

#buttons-container {
  display: flex;
  flex-direction: column;
  gap: 25px;
  width: 150px;
}

button {
  border: none;
  background: rgb(51, 131, 252);
  color: #fff;
  font-weight: 700;
  padding: 10px;
  cursor: pointer;
  transition: 0.5s;
}

button:hover {
  background: gainsboro;
}

input {
  padding: 5px;
  margin-top: 5px;
  width: 100%;
}
  • The progress container has a gray background (gainsboro) and a width of 100%, so it will be always as wide as the screen
  • The progress bar has a blue background (RGB(51, 131, 252)), a height of 100% (so it fills the same height as the container), and a width set to 0
  • The button has a hover effect with a transition of 0.5s
  • And I used flexbox to lay out the elements

JavaScript code

const progressBar = document.getElementById('progress-bar');
const runProgressButton = document.getElementById('run-progress');
const progressNumber = document.getElementById('progress-number');

const runProgress = () => {
  let width = 0;
  const progressInterval = () => {
    // if there is a number value in the input, then run the progress until the given value
    if (progressNumber.value) {
      if (width >= 100 || width >= progressNumber.value) {
        clearInterval(intervalId);
        progressNumber.value = '';
      } else {
        width++;
        progressBar.style.width = `${width}%`;
        progressBar.innerText = `${width}%`;
      }
    } else {
      // if there is no number value in the input, then just run the progress until 100%
      if (width >= 100) {
        clearInterval(intervalId);
      } else {
        width++;
        progressBar.style.width = `${width}%`;
        progressBar.innerText = `${width}%`;
      }
    }
  };

  let intervalId = setInterval(progressInterval, 10);
};

runProgressButton.addEventListener('click', runProgress);

Whenever we have to do something with HTML elements using JavaScript, we have to get them first somehow. This is called, manipulating the DOM (Document Object Model). I'm using the getElementById method (a method that references/get the element by its id) on the document object to get the progress bar, the button, and the input field. All three of them are stored in variables at the top of the file.
After that, I have a function called runProgress. This function gets called every time we click the button. You can see at the bottom of the file, I added an event listener to the button which listens for a click event. Once it heard the click event, it calls the function, runProgress.

So until now, it's quite straightforward. Let's look at the functionality now which needs more explanation.

The very first thing I did in the function is I declared a variable called, width. I declared it with the let keyword because this value will be changing inside the function and assigned the value 0. So whenever we click the button, the function runs and sets the width back to 0.

After that, there's another function called, progressInterval.

This is where the logic happens. It's pretty simple.

I declared a variable called intervalId at the bottom of the function, here I assigned the setInterval method which contains the function name as the first argument (progressInterval) and the delay time in milliseconds as the second argument. The delay could be any number, it depends on our preference how much we want the delay to be. This interval will run until a certain condition is met.

if (progressNumber.value) {
      if (width >= 100 || width >= progressNumber.value) {
        clearInterval(intervalId);
        progressNumber.value = '';
      } else {
        width++;
        progressBar.style.width = `${width}%`;
        progressBar.innerText = `${width}%`;
      }

I have an if-else statement inside the progressInterval function. The condition checks whether we have a value (number) set in the input field. If we do have a number, then I check for another condition with another if-else statement. So if the progress bar's width is equal or greater than 100 OR if the width is greater or equal to the value we passed in the input field, if any of this is true, then we clear the interval with the clearInterval method and we reset the input field to an empty string, so the number will disappear.

If none of the above conditions are true, then we will increment the width by 1 each time and we set the progress bar's width to be equal to the width variable, so the width will grow until it meets any of the conditions. Also, I added a text (with the innerText) inside the progress bar which indicates the percentage of the progress so we can see how much is the progress.

} else {
      // if there is no number value in the input, then just run the progress until 100%
      if (width >= 100) {
        clearInterval(intervalId);
      } else {
        width++;
        progressBar.style.width = `${width}%`;
        progressBar.innerText = `${width}%`;
      }
    }

You can see that this part is the same as the first part of the if-else statement, the only difference is that, if we don't have a value set in the input field, then the progress will just run until it reaches 100, and once it reaches the end, it calls the clearInterval method to stop the interval.

When we click the run progress button without a value in our input field, the width will be reset to 0 every single time the function gets called and will run until 100%.

So that's all about the progress bar, this is just a simple version of it but we can customize it more to our needs if we want to.

Here is the live link so you can try it out as well: Progress Bar

Progress Bar with JavaScript
Share this