Creating a Gradient Reading Progress Bar in NextJS with TailwindCSS

I am building this portfolio website to showcase my app and services to the world. During my research on portfolio blog sites, I came across a reading progress bar that is placed at the top of the page to indicate how much of the post is left to read.

This progress bar is a good way to know how much content is remaining and it provides feedback to the user, potentially improving the user experience of the website.


I found a tutorial by Anshuman Bhardwaj that explains how to implement a reading progress bar in a React and TailwindCSS project. Since my site is built with NextJS and TailwindCSS, I was able to adapt the tutorial to suit my website.

Let's see how to create a reading progress bar like the one on my website.

Getting Started

If you want to access the full source code for this project, you can find it on the tutorial's below source code section.

Create a Hook File in Your NextJS Project


Copy this code snippet below and save it as useReadingProgressbar.ts file.

Code snippet

1import { useEffect, useState } from "react"; 2import { useRouter } from "next/router"; 3 4/** 5 * React Hook to get the scroll percentage from the page, returns value from 0 to 100 6 */ 7export function useReadingProgress() { 8 const [completion, setCompletion] = useState(0); 9 const router = useRouter(); 10 11 useEffect(() => { 12 function updateScrollCompletion() { 13 // see how much we have scrolled 14 const currentProgress = window.scrollY; 15 // see how much total scroll is available 16 const scrollHeight = document.body.scrollHeight - window.innerHeight; 17 if (scrollHeight) { 18 setCompletion( 19 Number((currentProgress / scrollHeight).toFixed(2)) * 100 20 ); 21 } 22 } 23 24 function handleRouteChange() { 25 setCompletion(0); // Reset completion when the route changes 26 } 27 28 // Add scroll and route change event listeners 29 window.addEventListener("scroll", updateScrollCompletion); 30"routeChangeStart", handleRouteChange); 31 32 // Remove event listeners on unmount 33 return () => { 34 window.removeEventListener("scroll", updateScrollCompletion); 35"routeChangeStart", handleRouteChange); 36 }; 37 }, [router]); 38 39 return completion; 40}

This code snippet was obtained from Anshuman Bhardwaj's blog post. I have added an additional NextJS router event to reset the completion to 0 when the page changes. This ensures that the reading progress bar will be updated when a user visits another blog post.


1import { useReadingProgress } from "~/hooks/useReadingProgressbar"; 2 3export default function Header() { 4 const completion = useReadingProgress(); 5 6 return ( 7 <header 8 style={{ 9 backgroundSize: `${completion}%`, 10 backgroundRepeat: "no-repeat", 11 }} 12 className="sticky top-0 h-14 w-full bg-gradient-to-r from-red-500/30 from-30% to-blue-500/50 to-100% backdrop-blur-sm transition-all duration-500 ease-in-out " 13 > 14 <div className="text-center text-white">Header</div> 15 </header> 16 ); 17}

I have used a TailwindCSS gradient and adjusted the backgroundSize CSS property to reflect the completion percentage. This also supports the transition utility for smooth animations.


Preview tutorial project

Source Code

You can find the source code for this tutorial on

You can also see the implementation of this reading progress bar on the PNP website, which is an open-source project.


That's it! If you have any questions, feel free to ask in the comment box below. šŸš€šŸš€šŸš€šŸš€

Post date:
Read time: 2 min