DEV Community

Cover image for JavaScript Page Scroll Progress Bar
SAGNIK KUNDU
SAGNIK KUNDU

Posted on

JavaScript Page Scroll Progress Bar

You must have come across different blog/news article websites with progress bar at the top of the page, which keeps on changing as you scroll through the whole page. Here, we will see how to implement it using HTML, CSS, and simple JavaScript.

Example Image
You may directly access the codepen here.

First, add an empty div with id progressBar right after the opening body tag in HTML markup. This markup will stay fixed at the top of our page. To achieve that, let’s add some CSS properties to it.



<div class="progressBar"></div>


Enter fullscreen mode Exit fullscreen mode

The div is initially empty, so any changes in the width of the indicator will affect the width of the whole div (aka the progress bar). Starting with a width:0, we will calculate and vary the style of this width, as we scroll through the whole page using JavaScript.



.progressBar {
        position: fixed;
    top: 0;
    left: 0;
    height: 8px;
    background: linear-gradient(to right, #ff5f6d, #ffc371);
    width: 0%;
    z-index: 100;
    transition: width 0.2s ease-out;
}


Enter fullscreen mode Exit fullscreen mode

Let’s talk about the fun part, adding the JavaScript.

We select progressBar id and section selector. Then pass them as parameters in document method querySelector() which returns the first element within the document that matches the specified selector.



const progressBar = document.querySelector('.progressBar');
const section = document.querySelector('section');


Enter fullscreen mode Exit fullscreen mode

Now declare an arrow function named scrollProgressBar, within which we make a few calculations. As scrollDistance defines the size of the section and its position relative to the viewport. Although in our case, we only need the top distance so we write section.getBoundingClientRect().top. As we need to convert this value into a percentage later, a positive value will be the best fit to work with.



let scrollDistance = -(section.getBoundingClientRect().top);


Enter fullscreen mode Exit fullscreen mode

We could’ve used good old Math.abs() method to return the absolute value of the top, instead we will take the negative(-ve) value of it, to convert it into a positive value. While implementing further logic for the scroll bar we will find out why.

Viewport Image

Imagine the complete rectangle is the viewport of the website. In the beginning, the viewport stays at the top of the webpage, when the width of the progress bar is at width:0. If the webpage is scrollable enough then page length exceeds the viewport height and our scrollProgressBar function kicks in.

After that, progressPercentage will be calculated using the following formula:

Progress Percentage Formula
where, the numerator represents how much distance of the webpage has already been scrolled through and the denominator defines how much scroll distance is remaining to reach the end of the webpage.

  • Now one problem may arise that viewport height is the top viewport height so it never really reaches the bottom of the page. Thus, we need to subtract the document height from the section height.

  • Multiplying this fraction to 100 will eventually generate the percentage index for the progress bar.

  • Applying Math.floor() on it returns the largest integer less than or equal to the decimal value.



let progressPercentage =(scrollDistance/(section.getBoundingClientRect().height - document.documentElement.clientHeight)) * 100;

let val = Math.floor(progressPercentage);


Enter fullscreen mode Exit fullscreen mode

With the help of this val, we calculate the width styling of the progress bar using the HTML DOM (that allows JavaScript to change the style of HTML elements) by concatenating it with the ‘%’ sign.



progressBar.style.width = val + '%';


Enter fullscreen mode Exit fullscreen mode

Adding scroll event to the event listener finally gives the increase in progress bar width as the user scrolls through the page.



window.addEventListener('scroll', scrollProgressBar);


Enter fullscreen mode Exit fullscreen mode

Up to this point have to realize why using Math.abs() is not a clever idea. It is simply because the scrollDistance never really reaches zero value (0). So for our convenience, we convert it to zero (0) for any value of val < 0.



if (val < 0) {
        progressBar.style.width = '0%';
    }


Enter fullscreen mode Exit fullscreen mode

The complete code look something like:



const progressBar = document.querySelector('.progressBar');
const section = document.querySelector('section');

const scrollProgressBar = () => {
    let scrollDistance = -(section.getBoundingClientRect().top);
    let progressPercentage =
        (scrollDistance /
            (section.getBoundingClientRect().height - 
                document.documentElement.clientHeight)) * 100;

    let val = Math.floor(progressPercentage);
    progressBar.style.width = val + '%';

    if (val < 0) {
        progressBar.style.width = '0%';
    }
};

window.addEventListener('scroll', scrollProgressBar);


Enter fullscreen mode Exit fullscreen mode

Now, if all the steps are done correctly you should see your very own progress bar animation as you scroll through the website, no matter what is the size of your screen, which means it is completely responsive.

Top comments (2)

Collapse
 
sh20raj profile image
Collapse
 
pedrocampana profile image
PedroCampana

Thank you for this tutorial!