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! 😃 🙌