Scroll Text Reveal
PronewText that brightens word by word as it scrolls through view, in flow or pinned in place.
Every component ships as source. The shadcn CLI copies it into your repo, and from then on it is yours to read, change and delete. No package to upgrade, no styles to override.
Installation
npx shadcn@latest add @blank-pro/scroll-text-revealNeeds a Blank Pro licence key and the @blank-pro registry. Set up Pro access
Usage
import { ScrollTextReveal } from "@/components/ui/scroll-text-reveal"<ScrollTextReveal textClassName="text-3xl font-medium">
Every component ships as source.
</ScrollTextReveal>Each word owns a slice of the scroll progress, and the slices overlap, so the
reveal moves through the sentence as a wave. By default it runs while the text
travels from the bottom tenth of the viewport to just past the middle; offset
takes any useScroll offset to change that.
Only opacity — and, with effect="blur", a filter — is animated, so the text
never moves or reflows. Screen readers get the sentence once, from a visually
hidden copy; the animated words are hidden from them. With
prefers-reduced-motion the text renders fully revealed.
Inside a scrollable element rather than the page, pass its ref as container
and give that element a position (relative is enough) — scroll offsets are
measured from it.
Examples
Pinned
sticky makes the root height tall and pins the text while the reveal plays
across that distance. Here it also splits by character and sharpens each letter
from a blur.
The text holds still while you scroll, and comes into focus one letter at a time.
API Reference
ScrollTextReveal takes every div prop for its root, plus:
| Prop | Type | Default |
|---|---|---|
children | string | — |
as | "p" | "h1" | "h2" | "h3" | "h4" | "blockquote" | "div" | "p" |
split | "word" | "character" | "word" |
effect | "fade" | "blur" | "fade" |
dimOpacity | number | 0.15 |
sticky | boolean | false |
height | string | "200vh" |
container | RefObject<HTMLElement | null> | the window |
offset | useScroll offset | ["start 0.9", "end 0.55"], or ["start start", "end end"] when sticky |
textClassName | string | — |
Character splitting uses Intl.Segmenter, so emoji and combined characters stay
whole, and words never break across lines mid-reveal.