Animations

Scroll Text Reveal

Pronew

Text that brightens word by word as it scrolls through view, in flow or pinned in place.

Scroll inside the frame

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-reveal

Needs 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:

PropTypeDefault
childrenstring—
as"p" | "h1" | "h2" | "h3" | "h4" | "blockquote" | "div""p"
split"word" | "character""word"
effect"fade" | "blur""fade"
dimOpacitynumber0.15
stickybooleanfalse
heightstring"200vh"
containerRefObject<HTMLElement | null>the window
offsetuseScroll offset["start 0.9", "end 0.55"], or ["start start", "end end"] when sticky
textClassNamestring—

Character splitting uses Intl.Segmenter, so emoji and combined characters stay whole, and words never break across lines mid-reveal.