DEV Community

Cover image for Creating a Read Progress Bar in React with TailwindCSS
Anshuman Bhardwaj
Anshuman Bhardwaj

Posted on • Updated on • Originally published at theanshuman.dev

Creating a Read Progress Bar in React with TailwindCSS

Recently, I was reading one of my favorite author's articles on his website. I realized he has a reading progress bar at the top, which helps gauge how much of the article is left to read.

I thought this makes for a good user experience, and I should add this to my articles on my personal website as well. So, I went ahead and did it.

Breakdown

  1. Find how much a user can scroll down on this page.
  2. Find how much the user has scrolled down on the page.
  3. Get the ratio by dividing the later by the former.

Voila, there we have our scroll percentage aka "reading progress".

Progress indicator

Code snippet

import { useEffect, useState } from "react";

/**
 * React Hook to get the scroll percentage from the page, returns value from 0 to 100
 */
export function useReadingProgress() {
  const [completion, setCompletion] = useState(0);
  useEffect(() => {
    function updateScrollCompletion() {
      // see how much we have scrolled
      const currentProgress = window.scrollY;
      // see how much total scroll is available
      let scrollHeight = document.body.scrollHeight - window.innerHeight;
      if (scrollHeight) {
        setCompletion(
          Number((currentProgress / scrollHeight).toFixed(2)) * 100
        );
      }
    }
    // add scroll event listener
    window.addEventListener("scroll", updateScrollCompletion);

    // remove scroll event listener on umount
    return () => {
      window.removeEventListener("scroll", updateScrollCompletion);
    };
  }, []);
  return completion;
}
Enter fullscreen mode Exit fullscreen mode

The rest of the work is to show this information on the UI, for that, I just show a progress bar on the NavBar up top.

Styling

I use TailwindCSS for my website and it was very easy to make this progress bar with it

export default function NavBar() {
  const completion = useReadingProgress();
  return (
    <nav className="sticky z-50 top-0 backdrop-blur-3xl py-2">
      <span
        id="progress-bar"
        style={{
          transform: `translateX(${completion - 100}%)`,
        }}
        className={`absolute bottom-0 w-full transition-transform duration-150 h-1 bg-yellow-400`}
      />
      {/* Rest of the NavBar */}
    </nav>
  );
}
Enter fullscreen mode Exit fullscreen mode

We use the transform and translate CSS properties to make the UI for the progress bar.

The #progress-bar is by default exists at the bottom of NavBar but by using translateX we move it across the X-axis.

Because we do translateX(${completion - 100}%)

  • At 0% progress, it translates -100% on the X-axis, making it disappear
  • At 100% progress, it translates 0% on the X-axis, showing it fully

That's it for now. I hope you find this article helpful! Should you have any feedback or questions, please feel free to put them in the comments below, I would love to hear and work on them.

For more such content, please follow me on Twitter

Until next time

Latest comments (8)

Collapse
 
drfcozapata profile image
Francisco Zapata

Great!!! Thanks bro

Collapse
 
anshuman_bhardwaj profile image
Anshuman Bhardwaj

Glad, you liked it Francisco. Thanks for your feedback.

Collapse
 
mahbubhasanhira profile image
Mahbub Hasan Hira

Explain in shortcut. Great!! 😃

Collapse
 
anshuman_bhardwaj profile image
Anshuman Bhardwaj

Thanks man, will make more of these shorties

Collapse
 
soycamis profile image
Camilo Sosa

Good!

Collapse
 
anshuman_bhardwaj profile image
Anshuman Bhardwaj

Thanks Camilo

Collapse
 
anshuman_bhardwaj profile image
Anshuman Bhardwaj

Thanks Anjan, I had fun doing it

Collapse
 
ashu96 profile image
Ashutosh

nicely explained, looks good on the website as well.