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
- Find how much a user can scroll down on this page.
- Find how much the user has scrolled down on the page.
- Get the ratio by dividing the later by the former.
Voila, there we have our scroll percentage aka "reading progress".
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;
}
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>
);
}
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
Top comments (8)
Great!!! Thanks bro
Glad, you liked it Francisco. Thanks for your feedback.
nicely explained, looks good on the website as well.
Good!
Thanks Camilo
Thanks Anjan, I had fun doing it
Explain in shortcut. Great!! 😃
Thanks man, will make more of these shorties