Enhancing Your Blog with a Reading Progress Bar

While browsing various blogs online, I noticed a neat feature on some of them - a reading progress bar. This little bar at the top of the page provides a visual cue indicating how far the reader has progressed in the post. I decided to code one myself.

In this short post, I will share how to implement a reading progress bar for your blog built in React. It's a simple addition that can significantly enhance your users' reading experience. Let's dive straight into it!

In our ProgressBar component, we use React's useState hook to keep track of the user's scroll progress.

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

The scroll variable represents the current scroll progress as a value between 0 and 1. setScroll is the function we use to update that value.

Next, we define a function handleScroll that calculates the user's scroll progress.

const handleScroll = () => {
  const totalScroll = document.documentElement.scrollTop;
  const windowHeight = 
	document.documentElement.scrollHeight - 
	document.documentElement.clientHeight;
  const scrollPercent = totalScroll / windowHeight;

  setScroll(scrollPercent);
};

In handleScroll, we first get the total amount the user has scrolled (totalScroll) and the total scrollable height of the window (windowHeight). We then calculate the scroll progress as a ratio (scrollPercent) and update our scroll state with this new value.

Next, we use React's useEffect hook. This hook runs our code after the component renders and re-renders. In our case, we set up a scroll event listener when the component first mounts. This listener fires handleScroll each time the user scrolls. To clean up, we remove the event listener when the component unmounts.

useEffect(() => {
  window.addEventListener("scroll", handleScroll);
  return () => {
    window.removeEventListener("scroll", handleScroll);
  };
}, []);

Finally, we return the JSX that represents our progress bar.

return (
  <div className="fixed top-0 left-0 w-full h-1 bg-neutral-200 z-20">
    <div
      className="absolute top-0 left-0 h-full bg-red-600 origin-left"
      style={{ transform: `scaleX(${scroll})`, width: "100%" }}
    />
  </div>
);

Here we have a parent div that serves as the container of our progress bar. It's positioned at the top of the page and stretches the entire width.

The child div is the actual progress bar. We use the scroll state to adjust its width, making it look like it's filling up the container as the user scrolls down.

Here is the full ProgressBar component:

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

  const handleScroll = () => {
    const totalScroll = document.documentElement.scrollTop;
    const windowHeight =
      document.documentElement.scrollHeight -
      document.documentElement.clientHeight;
    const scrollPercent = totalScroll / windowHeight;

    setScroll(scrollPercent);
  };

  useEffect(() => {
    window.addEventListener("scroll", handleScroll);
    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);

  return (
    <div className="fixed top-0 left-0 w-full h-1 bg-neutral-200 z-20">
      <div
        className="absolute top-0 left-0 h-full bg-red-600 origin-left"
        style={{ transform: `scaleX(${scroll})`, width: "100%" }}
      />
    </div>
  );
};

Here is a codepen for this component.

Final Thoughts

Adding a reading progress bar like our ProgressBar can give your readers a visual map of their journey through your content. This can make your site more engaging and encourage more complete readings of your articles.

However, it's not always the right choice for every blog. Some users may find it distracting, and it might add little value to shorter pages. Since all browsers already have a native scrollbar, some may view it as redundant. Also, keep in mind that this is an extra piece of code you'll need to maintain.

But in the end, the choice is yours. In web design and development, there's always room to experiment. So why not give it a go? It may be the missing piece your blog needs.

Please, don't hesitate to share your thoughts in the comments. Your feedback is invaluable. Happy coding! 😃 🙌

UiComponentsReactUx
Avatar for Patrick Hladun

Written by Patrick Hladun

I'm a Frontend Developer and WordPress enthusiast on a mission to constantly improve my skills and keep up with the latest technology trends.

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.