ScrollProgress
ComponentsReading progressDrop-in React reading-progress bar
Live demo
Install
$ npm install @usefy/scroll-progressQuick start
import { ScrollProgress } from "@usefy/scroll-progress";
function App() {
return (
<>
{/* Mount once — a 3px blue bar fixed to the top of the viewport */}
<ScrollProgress />
<YourApp />
</>
);
}API reference
<ScrollProgress /> Props
| Prop | Type | Default | Description |
|---|---|---|---|
position | "top" | "bottom" | "top" | Which viewport edge the fixed bar is pinned to. |
color | string | "#3b82f6" | Bar fill color (any CSS color). |
height | number | string | 3 | Bar thickness — a number is pixels, a string is any CSS length. |
zIndex | number | 9999 | Stacking order of the fixed bar. |
target | RefObject<HTMLElement | null> | — (window) | Ref to the scrollable container to measure. Omit to track the window/document scroll. |
throttleMs | number | 0 | Throttle interval (ms) for scroll updates, forwarded to useScrollPosition. 0 updates on every scroll event. The trailing edge always fires, so the resting position is never dropped. |
aria-label | string | "Scroll progress" | Accessible name of the progressbar. |
render | (progress: number) => ReactNode | — | Escape hatch: replaces the default bar entirely; called on every render with the current progress (0–1). |
className | string | — | Class applied to the default bar element. |
style | CSSProperties | — | Inline styles merged over the defaults (yours win). |
Other exports
| Export | Description |
|---|---|
ScrollProgressProps | Props type. |
ScrollProgressPosition | "top" | "bottom". |
DEFAULT_BAR_COLOR / DEFAULT_BAR_HEIGHT / DEFAULT_Z_INDEX / DEFAULT_ARIA_LABEL | The defaults, for reuse in custom render UIs. |
The default bar also exposes a data-position="top" | "bottom" attribute for styling and testing.
Progress model
progress = clamp(scrollTop / (scrollHeight - clientHeight), 0, 1)
When scrollHeight - clientHeight <= 0 (the content fits in the viewport, so there is nothing to scroll), progress is 0 — the bar renders but stays empty, so layout and stacking never jump when content grows.
Go deeper
This page is the quick reference. For every example, prop, and edge case, read the full README — or open Storybook to change props live.