How to Display Progress Bar on Page Scroll with ReactJs

Previously, we have created a vertical scrollBar with CSS and JavaScript. Today, we are going to create a page scroll progress bar in ReactJs. We are going to use the ReactJs 16 and the Hook API.

React Project Setup

Let’s start with the create-react-app CLI tool to set up your project.

npx create-react-app react-scroll-progress-bar

Now go the project directory and start your react application with the npm start command.

cd react-scroll-progress-bar && npm start

Setup Style and Content

It’s time to add some basic style and content to our application. Now open the App.js file and add some content. You can use the lorem ipsum content to quickly add the page content.

function App() {

    return (
        <div className="App">
            <div>
                <p>Lorem ipsum dolor sit amet, ...</p>
                <p>Duis at nisl consectetur ...</p>
                ....
                ....
            </div>
        </div>
    );
}

export default App;

Now open the App.css file and add some basic style.

html {
    overflow: -moz-scrollbars-none;
    scrollbar-width: none;
}
  
body {
    background: #171414;
    font-family: "Courier New", Courier, monospace;
    color: #ffffff;
    padding: 5% 15%;
}
  
p {
    font-size: 1.8rem;
}
  
p:first-of-type {
    margin-top: 60px;
}

Create ProgressBar For Your React App

Now let’s create the progress bar with basic HTML and the CSS. We are going to use two div element, the first one will be the parent container. The parent container will hold up the progress bar, let’s call it the progress bar container. The second div element for the main progress bar that extends on the page scroll.

Open your App.js file and add both elements i.e. progress bar container and the progress bar to your app.

function App() {

    return (
        <div className="App">
            <div id="progressBarContainer">
                <div id="progressBar" />
            </div>
            ....
            ....
        </div>
    );
}

export default App;

Now add the progress bar related style to your App.css file.

#progressBarContainer {
    position: fixed;
    z-index: 10;
    background: rgba(255,255,255,0.05);
    width: 100%;
    top: 0;
    left: 0;
}
  
  
#progressBar {
    background: linear-gradient(to left, red, violet);
    transform-origin: top left;
    transform: scale(0,0);
    opacity: 0;
}

#progressBarContainer,
#progressBar {
    height: 10px;
}

As per the above codes, we have applied the light black color to the progress bar container. We have used the linear gradient to display the multi-color progress bar indicator.

Implement Progress Bar on Page Scroll

Now time to implement some logic to implement the progress bar on page scroll. We are going to call the scroll event with window.addEventListener('event_name', callback). Let’s create the callback function that triggers on page scroll.

let progressBarHandler = () => {

    const totalScroll = document.documentElement.scrollTop;
    const windowHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
    const scroll = `${totalScroll / windowHeight}`;
}

First, we have to detect how much we have scrolled the page from the top position. We have used the document.documentElement.scrollTop to get the number of pixels from the top. Now we have to get the exact window height. And if we get the total scroll height and the client height then can easily get the exact window height by subtracting the client height with scroll height.

We are going to use the element.clientHeight to get the inner height of an element in pixels. And the element.scrollHeight to measure the height of an element’s content including the not visible content on the screen.

This is how we get the window height.

const windowHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight

Now we can easily calculate the scroll duration with totalScroll and windowHeight. But it depends on how we are implementing the progress bar. We are using the CSS function scale() and the opacity property to display the progress bar. Both scale and the opacity requires the decimal value between 0 and 1. To get this value we need to divide the total scroll with window height.

const scroll = `${totalScroll / windowHeight}`;

Now define a state using useState with 0 value.

const [scroll, setScroll] = useState(0);

and update the scroll state value from the progressBarHandler function.

let progressBarHandler = () => {

    const totalScroll = document.documentElement.scrollTop;
    const windowHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
    const scroll = `${totalScroll / windowHeight}`;
    
    setScroll( scroll );
}

Now update the progress bar style based on the scroll state value.

<div id="progressBarContainer">
    <div id="progressBar" style={{transform: `scale(${scroll}, 1)`, opacity: `${scroll}`}} />
</div>

Implement Progress Bar with React Hook

Now time to handle the window.addEventListener with React Hook. We are going to use the useEffect() hook. The useEffect hook works similar to the React lifecycle methods like componentDidMount, componentWillUnmount. First, let’s mount the event.

useEffect(() => {
    ....
    ....
});

Now, add the event handler within the useEffect hook.

useEffect(() => {

    window.addEventListener("scroll", progressBarHandler);
});

This is how componentDidMount implements through useEffect hook. Now we have to return the callback to implement componentWillUnmount.

useEffect(() => {

    window.addEventListener("scroll", progressBarHandler);

    return () => window.removeEventListener("scroll", progressBarHandler);
});

Now the final step is to move our progressBarHandler function within the useEffect hook.

const [scroll, setScroll] = useState(0);

useEffect(() => {

    let progressBarHandler = () => {
        
        const totalScroll = document.documentElement.scrollTop;
        const windowHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
        const scroll = `${totalScroll / windowHeight}`;

        setScroll(scroll);
    }

    window.addEventListener("scroll", progressBarHandler);

    return () => window.removeEventListener("scroll", progressBarHandler);
});

We hope this article to display progress bar on page scroll in ReactJs. If you like this article then please follow us on Facebook and Twitter.