Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Pop Text for React

Text that pops in like a comic-book sound effect, each letter springing past its size with a burst of rays. For React with Base UI, when a word should land with a bang.

Framework

Pop Text springs each letter onto the page from nothing, past its full size and back with a small bounce, while a starburst of thin rays flashes behind it on impact. The letters land one after another, like a sound effect in a comic. It plays once, when the text scrolls into view.

Use it for a win, a celebration, a playful heading or a call to action with energy, and keep it to a few words. For a heavier, hand-pressed landing, use Stamp Text; for letters that slide in without a bounce, Splitting Text. The bounce is a CSS keyframe animation the install adds to your stylesheet, and each burst is its letter's own ::before, rays drawn by a gradient, with no SVG and no animation library. With reduced motion the text is simply there, with no burst.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { PopText } from "@/components/ui/pop-text";
<h2>
  <PopText text="Level up!" />
</h2>

Demos

Color

burstColor takes any CSS colour, including your theme's variables such as var(--primary); by default the burst is the text's own colour.

Preview width

Words

by="words" pops each word whole, 200 ms apart, with a burst as wide as the word: for a short line, and for scripts whose letters join, such as Arabic, which a split between letters would break.

Preview width

Plain

burst={false} keeps the bounce and leaves out the rays, for a smaller, quieter line; a shorter stagger (50 ms rather than 80) suits it.

Preview width

Accessibility

Screen readers read the whole text once, as plain text: the popping letters and their bursts are hidden from them, and a visually hidden copy carries it. Words wrap whole, and the line keeps its direction on a right-to-left page. With reduced motion every letter is in place from the start and no burst shows.

FAQ

What is the burst made of?

Each letter's own ::before: eight thin rays drawn by a repeating conic gradient and cut into a ring by a radial mask, behind the letter. It adds no elements to the page and flashes for about a third of a second.

Can I make the bounce bigger or smaller?

In your CSS, --pop-text-scale is how far past its size a letter pops, 1.4 by default: 1.2 is gentler, 1.8 more cartoonish. duration is one letter's whole pop, 500 ms.

How much text can it take?

A few words. Each letter is its own pop, 80 ms after the last, so a long line takes long to land and its bursts crowd each other; for a sentence, use by="words".

When does the animation play?

Once, when at least a quarter of the text is in view: an IntersectionObserver on the text starts it, then stops watching. Pass trigger="mount" to play it as soon as the page shows it, for text that's always on screen.

How do I run something after it finishes?

Pass onComplete: it's called once, when the last letter or word has settled, such as to start confetti after it.

What happens with reduced motion?

No bounce and no burst: the text is there from the start, fully readable.

API Reference

PopText

<span> data-slot="pop-text"

PropType
textstring

The text.

burst?boolean

A comic burst of rays that flashes behind each character as it lands. @default true.

Default
true
burstColor?string

The burst's colour, any CSS colour; the text's own colour when unset.

by?"characters" | "words"

What pops on its own: each character, or each word (for scripts whose letters join, such as Arabic).

Type
"characters" | "words"
Default
"characters"
duration?number

How long one character or word takes to pop and settle, in milliseconds. @default 500.

onComplete?() → void

Called once the last character or word has settled.

Returns
void
stagger?number

The time between one character or word and the next, in milliseconds.

Default
80 (characters), 200 (words)
trigger?"mount" | "view"

When it plays: as soon as it's on the page, or once it scrolls into view.

Type
"mount" | "view"
Default
"view"
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

AttributeType
data-last?string
data-view?string

"in" when visible is true, otherwise "out".

CSS variableType
--pop-text-burst-colorstring

The burst's colour (the text's own).

--pop-text-durationstring

One unit's pop.

--pop-text-scalestring

How far past its size a unit pops (1.4).

All 97 text effects