DEV Community

Omkar Bhagat
Omkar Bhagat

Posted on • Updated on

Build A Simple Progress Bar

You might get this as an interview question for web development roles, especially front-end roles. I'll explain how you can ace it by creating a progress bar in minutes.

Spoiler: You could do it under a minute with CSS ;)

Step 1: Create the structure

Create the progress bar with plain HTML and CSS as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Progress Bar Tutorial</title>
    <style>
        .progress-bar-wrapper {
            width: 500px;
            height: 50px;
            background-color: #D5C67A;
            margin: 20px 0;
        }
        .progress-bar {
            height: 100%;
            width: 0%;
            background-color: #06A77D;
        }
    </style>
</head>
<body>
    <div class="progress-bar-wrapper">
        <div class="progress-bar"></div>
    </div>
    <button onclick="load_something(1)">Load</button>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

This results in the following empty progress bar:
Empty Progress Bar

You can already test it by manually increasing the width from 0% to 10% and so on!

There's a button in there which will trigger the function load_something(1) and pass seconds as value. In this case we are passing 1 second as the value.

We'll create that function in the next step.

Step 2: Add JavaScript

Add the following JS code before the closing body tag:

<script>
    function load_something(seconds) {
        const progress_bar = document.querySelector('.progress-bar')
        let percent = 0
        const interval = setInterval(() => {
            percent += 1
            progress_bar.style.width = percent + '%'
            if (percent > 100) {
                clearInterval(interval)
            }
        }, (seconds * 1000)/100);
    }
</script>
Enter fullscreen mode Exit fullscreen mode

This load_something function will perform the following steps:

  • Select the element with the progress-bar class.
  • Set percent to 0.
  • Create an interval which repeats every seconds/100. In each iteration it will set the width of the progress bar based on the value in percent and then increase the percent value by 1.
  • It will clear this interval only when percent is greater than 100.

Here's what that looks like:

Final Progress Bar

Step 3: Do it with CSS

What if I tell you we can avoid the second step completely by using CSS? Here's how –

<script>
    function load_something(seconds) {
        const progress_bar = document.querySelector('.progress-bar')
        progress_bar.style.transition = `${seconds}s linear width`
        progress_bar.style.width = '100%'
    }
</script>
Enter fullscreen mode Exit fullscreen mode

This will achieve the same result but I personally prefer this one as it is much cleaner and done with CSS (instead of intervals which can be a bit messy).

Let me know what you think about this in the comments.

Top comments (15)

Collapse
 
jonrandy profile image
Jon Randy 🎖️

The progress HTML element is probably a better choice here

Collapse
 
omkarscode profile image
Omkar Bhagat

Thanks Jon. I'll have a look!

Collapse
 
bemmio profile image
Edward Mike

Great content bro

Collapse
 
bemmio profile image
Edward Mike

Gh

Collapse
 
bemmio profile image
Edward Mike

Gh

Thread Thread
 
bemmio profile image
Edward Mike

Gh

Thread Thread
 
bemmio profile image
Edward Mike

Gh

Thread Thread
 
bemmio profile image
Edward Mike

Gh

Thread Thread
 
bemmio profile image
Edward Mike

Gh

Thread Thread
 
bemmio profile image
Edward Mike

Gh

Thread Thread
 
bemmio profile image
Edward Mike

Gh

Collapse
 
jacrys profile image
Keith Lewis

How does the "the" element render? Is it inline or block? 😉

Collapse
 
omkarscode profile image
Omkar Bhagat

lol Keith, thanks for a good laugh!

Collapse
 
dev_shubham profile image
Shubham Jadhav

Nice explanation, but including style in body is not good practice. You must create another css file or include in head tag.

Collapse
 
omkarscode profile image
Omkar Bhagat

Hi Shubham, I agree and edited the post with a fix. Thanks.