“Sticky” Content-Aware Progress Bar

Needed an easy solution for a discrete progress bar that would compete 100% at the end of the content, not at the end of the page. Most progress bars complete when you’ve hit the end of the page. I wanted to complete at the end of the content, so it needed a little love.

Here’s the ZIP file with the HTML, CSS, and the JS. Most of the heavy lifting is in the JavaScript file, but there’s also some important behavior in the CSS.

The JavaScript

The script tracks down the appropriate elements. Then it grabs styles associated with the header, main, and footer elements. We add a quick event listener to watch for when the user scrolls, and when they do, we fire the updateProgressBar() function.

// Get the important elements
const progressBar = document.getElementById('progressbar');
const mainElement = document.querySelector('main');
const headerElement = document.querySelector('header');
const footerElement = document.querySelector('footer');

// Get header height, main bottom margin, and set initial progress bar width
const { height: headerHeight } = getComputedStyle(headerElement);
const { marginBottom } = getComputedStyle(mainElement);
const progressBarMinWidth = 2;
progressBar.style.width = `${progressBarMinWidth}%`;

// Listen for the scroll event on the window
window.addEventListener('scroll', updateProgressBar);

function updateProgressBar() {
    // Calculate the scroll percentage
    const maxScrollHeight = document.documentElement.scrollHeight - window.innerHeight - footerElement.offsetHeight - parseFloat(marginBottom);
    const scrollPercentage = Math.min((window.scrollY / maxScrollHeight) * 100, 100);

    // Set the width of the progress bar based on the scroll percentage
    progressBar.style.width = `${Math.max(progressBarMinWidth, scrollPercentage)}%`;

    // Check if the user has scrolled past the header
    progressBar.classList.toggle('fixed', window.scrollY >= parseFloat(headerHeight));

    // Check if the progress bar is 100%    
    progressBar.classList.toggle('complete', window.scrollY >= maxScrollHeight );    
    
}

Progress Bar Initialized

The progress bar starts off at the bottom of the footer.

User Scrolls Past Header

Then, as the user scrolls past the header, the progress bar pins to the top and expands as the user scrolls through the content.

User Finishes Content

Note that the vertical scroll bar has some more to go (for the footer that I made inordinately large for this demo). Even though there’s more vertical scroll, the progress meter is registering complete. I added a little checkmark embellishment to further visually conform that the content is complete.

Scrolling Past End of Meaningful Content

The user can continue scrolling to reach the bottom of the page itself.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *