Adding a Progress Bar to your Next.js application is a great way to enhance the user experience (UX) by visually indicating that a page is loading or transitioning. In this article, we’ll guide you on how to create a simple Progress Bar in Next.js.
Next.js provides a utility called router.events
to listen to various routing events. These include:
routeChangeStart
(when a page transition starts)routeChangeComplete
(when a page transition completes)routeChangeError
(when an error occurs during the transition)
Let’s create a new file called ProgressBar.jsx
and write the following code:
jsximport { useState, useEffect } from "react"; import { useRouter } from "next/router"; const ProgressBar = () => { const [progress, setProgress] = useState(0); // Tracks progress percentage const [loading, setLoading] = useState(false); // Tracks loading state const router = useRouter(); useEffect(() => { const handleRouteChangeStart = () => { setLoading(true); setProgress(30); // Initialize Progress Bar at 30% }; const handleRouteChangeComplete = () => { setProgress(100); // Set progress to 100% setTimeout(() => { setLoading(false); setProgress(0); // Reset Progress Bar }, 300); // Add a delay for a smoother animation }; // Attach event handlers router.events.on("routeChangeStart", handleRouteChangeStart); router.events.on("routeChangeComplete", handleRouteChangeComplete); router.events.on("routeChangeError", handleRouteChangeComplete); // Cleanup event handlers when the component unmounts return () => { router.events.off("routeChangeStart", handleRouteChangeStart); router.events.off("routeChangeComplete", handleRouteChangeComplete); router.events.off("routeChangeError", handleRouteChangeComplete); }; }, [router]); return ( <div style={{ position: "fixed", top: 0, left: 0, width: `${progress}%`, // Set width based on progress height: "5px", // Bar height backgroundColor: "#0070f3", // Bar color transition: "width 0.3s ease, opacity 0.3s ease", // Smooth transition effect opacity: loading ? 1 : 0, // Show bar only when loading zIndex: 1031, // Ensure the bar appears above other elements }} ></div> ); }; export default ProgressBar;
Next, include the ProgressBar
in your project’s _app.js
file so it displays across all pages:
jsximport "../styles/globals.css"; // Global CSS file import ProgressBar from "../components/ProgressBar"; // Import the Progress Bar export default function MyApp({ Component, pageProps }) { return ( <> <ProgressBar /> <Component {...pageProps} /> </> ); }
Optional: If you prefer using TailwindCSS for styling, you can replace the inline styles with Tailwind classes.
jsx<div className={`fixed top-0 left-0 h-1 bg-blue-500 transition-all duration-300 z-50 ${ loading ? "opacity-100" : "opacity-0" }`} style={{ width: `${progress}%`, }} ></div>