Creating Scroll Progress Bar using CSS and JavaScript in React

Suraj Vishwakarma - Feb 19 - - Dev Community

Introduction

We have seen a progress bar on the top of the blog-based website to show the reading progress. That looks cool and also lets the user know How many of the articles remain to be read.

Today, we are going to build such progress that will be responsive according to the size of the window and scroll bar. I will be creating this bar without any library by just using CSS and JavaScript. This will help us understand the logic behind building this feature.

We are going to go through:

  • Installing React
  • Building a static blog page
  • Adding CSS for the progress bar
  • Adding JavaScript to look for the scrollbar

As for the prerequisite, you must be familiar with web development. By Web development, I mean HTML, CSS, and JavaScript. As our front-end framework, React is our choice.

Let’s get started in building the application.

Environment Setup

Let’s first set up the environment before writing any code. Let’s first install React. Enter the below command in React for installing the React.

Note: To run the below code and other code in the terminal, we need to have nodejs pre-installed.



    npm create-react-app progress-bar


Enter fullscreen mode Exit fullscreen mode

We are going to build the progress bar without any library. That’s why we don’t need any other dependencies.

Working

Let’s first understand the working of the progress bar before writing any code. For changing the width of the bar as per the scroll, we need the following properties from the page:

  • The current position of the scroll: This will help us know the position. The progress bar will change as it changes. We can get this through the scroll listener. The value will be in pixels.
  • Total Scrollable area: To know the length of the progress bar, we should also need to know the total scrollable area. We can know it through the body’s clientHeight. It won't consider the margin and border while calculating the height. We don't require that area, we only need to focus on the content area. The value will be in pixels.
  • Size of Scrollbar: The current scrollbar position will start from 0 when at the top but since we will see some of the content on the page, we don’t need to start the progress bar from 0. The current position will be added to the size of the scroll bar to get to the bottom of the scrollbar. We can get the size of the scrollbar through the window’s innerHeight property. This will be also in pixels.

Image explaining scrollbar

Now, we have all the required properties to create the progress bar. The only problem is that all the properties are in pixels. If we want to implement a progress bar for only one screen size, we can do it with pixels as a unit. For responsiveness, we need to have a percentage as the unit.

We can get the percentage of the current position of the scrollbar in percentage with the total scrollable area using the below formula:



    ((scrollbar position + scrollabar height)/total scrollable area)*100


Enter fullscreen mode Exit fullscreen mode

This will provide us with a scrollbar position in percentage concerning the total scrollable area. It will be the width of the progress bar. Now, let’s implement this in our code.

App.js

We are going to implement the functionality in the App.js. Let’s look into the code one by one with explanations.

We are using three states for storing our three properties. You can check the comment for each state’s explanation.



    const [y, setY] = useState(window.scrollY); // storing current scroll bar positiotn
    const [totalY, setTotalY] = useState(); // storing Total Scrollable area
    const [scrollBar, setScrollBar] = useState(); // storing Size of scroll bar


Enter fullscreen mode Exit fullscreen mode

We need to change the progress bar as per changing the scrollbar. We can do it in React with useEffect hook that will look at the scroll bar position for any changes.



    useEffect(() => {
      window.addEventListener("scroll", () => setY(window.scrollY));
      const element = document.getElementsByTagName("body")[0];
      setTotalY(element.clientHeight);
      setScrollBar(window.innerHeight);
    }, [y]);


Enter fullscreen mode Exit fullscreen mode

As mentioned in the working section, we are getting all the necessary properties.

Now for the width of the progress bar, we have used the above properties in our formula with the percentage unit.



    const scroll = `${((y + scrollBar) / totalY) * 100}%`;


Enter fullscreen mode Exit fullscreen mode

Return

Our website will be a blog website that displays a progress bar according to the article’s length. So here is the JSX code of the return.



    <div>
        <div className="progress-bar" style={{ width: scroll }}></div> // This is our 
          progress bar
        <div className="container">
          <h1 className="title">How I build a Documentation site using Docz</h1>
          <img className="image" src="https://bit.ly/3TAF6Gu" />
          <div className="article">
            <h2>Introduction</h2>
            <p>
              Conten of the article. 
            </p>
          </div>
        </div>
      </div>


Enter fullscreen mode Exit fullscreen mode

Here is the CSS of the progress bar:



    .progress-bar {
      height: 20px;
      background-color: rgb(236, 20, 20);
      overflow: hidden;
      position: fixed;
      transition: width 2s;
    }


Enter fullscreen mode Exit fullscreen mode

We have transition properties for smooth animation when the scroll changes. With the position fixed, it will be fixed at the top and won’t hide when scrolled.

Demo

After adding all this you will be able to see the progress working. Here is a GIF showing it.

You can find the project and a live demonstration of it on CodeSandBox. The link to Codesandbox is here.

Connect with Me

Conclusion

We have successfully created a progress bar using JavaScript mostly with some CSS. We can use framer motion to create this animation easily but it's also interesting to know the behind-the-scenes of working for better understanding. Once you understand it, you can go with using any framework or library for implementing it.

I hope the article has helped you in building an awesome progress bar. Thanks for reading the blog post.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .