Scroll Progress Bar for React

Fixed bar at the top that scales horizontally with scroll progress. Uses Framer Motion for smooth updates.

Component

Scroll down to see the progress bar fill.

Section 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 3

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 4

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 5

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 6

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 7

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 8

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 9

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 10

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 11

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 12

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Installation

 

Usage

Import

Add the ScrollProgress import.

import { ScrollProgress } from "@/components/scroll-progress";

Use

Add to your layout (e.g. root layout).

<ScrollProgress />;

Guidelines

  • Place in your root layout so it tracks page scroll, or pass containerRef for a custom scroll container.
  • Use inline with containerRef when the bar should appear inside the scroll container (parent needs relative).
  • Use className to customize height, color, or position.
  • The bar scales from left to right; ensure sufficient scroll height to see the effect.

Props

All props are optional unless marked required. Use these to customize every aspect of the component.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the bar (e.g. height, color).
containerRefReact.RefObject<HTMLElement | null>undefinedRef to a scrollable overflow container. Omit to track window scroll instead.
inlinebooleanfalseWhen true, positions the bar absolutely inside its parent (use with relative container) instead of fixed to viewport.

Accessibility

  • Decorative visual indicator only; the bar is marked aria-hidden true and exposes no role, label, or accessible name to assistive technology.
  • There are no interactive controls, buttons, links, or focusable elements, so keyboard operability and focus visibility do not apply to this component.
  • Scroll position is already conveyed natively by the browser scrollbar, so screen reader and keyboard users lose no information when this purely visual layer is ignored.
  • It does not honour prefers-reduced-motion: the spring-driven scaleX always animates, so it should be guarded with a matchMedia('(prefers-reduced-motion: reduce)') check to disable the spring for users who prefer reduced motion.

Performance

  • Animates only scaleX (a transform) and opacity, both of which are GPU compositable and avoid layout or paint, making each scroll update cheap.
  • The scroll listener is registered with passive true so it never blocks the scroll thread, and it is removed in the useEffect cleanup to prevent leaks.
  • Uses Framer Motion useMotionValue and useSpring to smooth updates outside of React render, so scrolling does not trigger component re-renders.
  • A single requestAnimationFrame gates the initial opacity reveal, and no IntersectionObserver, will-change, or timers are used, keeping the footprint minimal.
  • Motion is never gated by reduced-motion or visibility, so the spring keeps animating on every scroll even for users who would prefer it disabled.

Examples

Basic

Add to your layout for a global scroll indicator.

Scroll down to see the progress bar fill.

Section 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 3

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 4

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 5

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 6

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 7

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 8

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 9

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 10

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 11

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 12

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

import { ScrollProgress } from "@/components/scroll-progress";

export function Layout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <>
      <ScrollProgress />
      {children}
    </>
  );
}

Custom styling

Customize height and color with className.

Scroll down to see the progress bar fill.

Section 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 3

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 4

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 5

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 6

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 7

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 8

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 9

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 10

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 11

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 12

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

import { ScrollProgress } from "@/components/scroll-progress";

<ScrollProgress className="h-0.5 bg-violet-500" />;

With container ref

Track scroll inside an overflow container. Use inline so the bar stays at top of the container.

Scroll down to see the progress bar fill.

Section 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 3

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 4

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 5

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 6

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 7

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 8

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 9

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 10

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 11

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Section 12

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

import { useRef } from "react";
import { ScrollProgress } from "@/components/scroll-progress";

export function ScrollableSection() {
  const containerRef = useRef<HTMLDivElement>(null);

  return (
    <div
      ref={containerRef}
      className="relative h-96 overflow-y-auto"
    >
      <ScrollProgress containerRef={containerRef} inline />
      <div className="p-4">{/* content */}</div>
    </div>
  );
}

Last updated on Jun 19

Made with ❤️ by Pulkit &

© 2026 Pulkit. All rights reserved

Last updated: