Skip to content
Textlab
1
Browse

ComponentsScroll

Scroll fill

Words light up as you read down the page.

Scroll inside the preview ↓

We believe the best interfaces disappear. You notice what you came for, not the tool in between, and every word earns its place.

Installation

$ npx shadcn@latest add @textlab/scroll-fill

Needs @textlab in your components.json. Setup takes a minute.

Usage

usage.tsx
import { ScrollFill } from "@/components/textlab/scroll-fill/scroll-fill";

<ScrollFill text="We believe the best interfaces disappear. You notice what you came for, not the tool in between." />

Variants

wordcharline

Props

PropTypeDefaultDescription
text*string–The copy.
variant"word" | "char" | "line""word"What lights up as one unit.
dimnumber0.18Opacity of text not yet reached.
containerRefObject<HTMLElement>–Scrollable ancestor to track. Defaults to the window.
offset[string, string]["start 0.85", "end 0.45"]Where filling starts and ends, in motion scroll-offset syntax.
asElementType"p"Rendered element.
reducedMotion"user" | "always" | "never""user"user follows the OS setting; always shows the still version.
classNamestring–Merged onto the root.

When to use it

Reach for it

  • Manifesto paragraphs and mission statements.
  • A key paragraph you want people to actually read.

Skip it

  • Every paragraph on a page; the effect loses meaning.
  • Text above the fold that should be readable at once.

Accessibility and motion

Accessibility

  • The full paragraph is read once from a hidden copy.
  • Dim text keeps its shape, so nothing is hidden from sighted readers who scroll fast.

Motion

  • Progress is tied to scroll position, not time, so it reverses when you scroll up.
  • Filling starts as the paragraph enters the lower part of the viewport.
Reduced motion. The paragraph shows at full opacity.

Performance

  • Opacity only. One derived motion value per unit, no React renders while scrolling.