Page scroll progress with JavaScript

I recently saw a blog had used the scroll progress of page in percentage on every post. I liked the idea so thought why not try it and create a JavaScript snippet. So here we are.

Note: I'm not using jQuery. Its plain JavaScript. But it can also be done with jQuery. Of course, the code below can be used with jQuery too.

Demo

Listen to scroll event

We'll add an addEventListener to window object. What are your thoughts on using document here instead?

window.addEventListener('scroll', function() {});
// in jQuery:
$(window).on('scroll', function(){});

But I suggest you attach this event after DOM has been loaded like so:

document.addEventListener('DOMContentLoaded', function() {
    window.addEventListener('scroll', function() {});
});
// in jQuery
$(function() {
    $(window).on('scroll', function(){});
})();

Calculate the progress

Here is the formula I spent a lot of time to make.

progress = (document.body.scrollTop / ( document.body.scrollHeight - window.innerHeight ) ) * 100;

We'll do this calculation on every scroll event. Means we'll be doing it like:

document.addEventListener('DOMContentLoaded', function() {
    window.addEventListener('scroll', function() {
        progress = (document.body.scrollTop / ( document.body.scrollHeight - window.innerHeight ) ) * 100;

        // console.log(progress);
    });
});

Do something with progress

I'll just define another function to be called whenever progress is updated.

fucntion updateProgress( progress ) {
    // Do whatever you like
    console.log( progress );
}

var progress = 0;
document.addEventListener('DOMContentLoaded', function() {
    window.addEventListener('scroll', function() {
        progress = (document.body.scrollTop / ( document.body.scrollHeight - window.innerHeight ) ) * 100;

        updateProgress( progress );
    });
});

And we are done. Now you can use that progress in percentage to do whatever you want.

Extra bit

I also wanted to track the time it took for full page scroll. So I added the following code.

function updateProgress( progress ) {
    // Do whatever you like
    console.log( 'You have scrolled:', progress, '%' );
}

function endOfPage( time ) {
    // in miliseconds
    console.log( 'The time you took to reach end:', time/1000, 'Seconds' );
}

var progress = 0,
end = false,
timeStart = null,
timeEnd = null;

document.addEventListener('DOMContentLoaded', function() {
    window.addEventListener('scroll', function() {
        if(timeStart == null)
            timeStart = Date.now();

        progress = (document.body.scrollTop / ( document.body.scrollHeight - window.innerHeight ) ) * 100;

        updateProgress( progress );

        if(progress >= 100 && !end) {
            timeEnd = Date.now();
            end = true;
            endOfPage( timeEnd - timeStart ); // Call the other function
        }
    });
});

Gist

I've also created a gist for this purpose.

How to use:

scrollProgress (el, updateFunc, endFunc);

el: It accepts window or id of an element.

updateFunc: Function to be called on every update of scroll. Progress percentage will be passed as parameter.

endFunc: Function to be called when scroll has reached the end for the first time. Total time taken in milliseconds will be passed.

Example:

scrollProgress (window, updateFunc, endFunc);
// or
scrollProgress ('idOfDiv', function(p) {
    console.log(p + '% Scrolled');
}, function(time) {
    console.log('End reached in', time/1000, 'Seconds');
});

Thoughts or Suggestions: