shadcn.io is not affiliated with official shadcn/ui
Stretch Text squashes and stretches a line one letter at a time: each one squashes flat and wide against the line, springs up tall and thin, then settles, the way a cartoon animator draws an impact. A ripple of them runs through the word, then the line rests before the next round.
Use it for a playful headline, a game, a kids' app, a button label that should feel springy. For letters that leap off the line instead of changing shape, use Bouncing Text; for letters that rock in place, Wobble Text. Each letter runs a CSS keyframe animation the install adds to your stylesheet, scaled from its foot and delayed by its place in the text, with no animation library. With reduced motion the text keeps its shape.
Installation
Usage
import { StretchText } from "@/components/ui/stretch-text";<h1>
<StretchText text="Boing!" />
</h1>Demos
Intensity
intensity is how far each letter squashes: subtle gives up 15% of its height, medium, the default, a quarter, strong about a third. Each letter widens as it flattens, so it keeps about the same area.
Stagger
stagger is the time between one letter squashing and the next, 80 ms by default: a short one sends a quick ripple through the word, a long one lets each letter land on its own. loop={false} plays one round when the page shows the text.
Accessibility
Screen readers read the text once, as plain text, from a visually hidden copy; the stretching letters are hidden from them. Words wrap whole, and the line keeps its direction on a right-to-left page. No letter loses more than about a third of its height, and only for a moment, so the text stays readable. With reduced motion it keeps its shape.
FAQ
What is squash and stretch?
The first principle of cartoon animation: a thing flattens as it hits and stretches as it springs away, keeping its volume. Each letter here gets shorter and wider, then taller and thinner, then settles, which is what makes it read as rubber rather than a glitch.
Why do the letters seem to hit the ground?
Each letter is scaled from its foot, so its base stays on the line and only its top moves, as if it landed there.
Why do the rounds overlap in a long text?
A round is duration, 2000 ms by default, and the squash and stretch take its first two fifths. When the ripple through a long text takes longer than the rest of the round, the first letters start again before the last have settled. Lengthen duration or shorten stagger to keep the rounds apart.
How is it different from Bouncing Text?
Stretch Text keeps every letter on the line and changes its shape. Bouncing Text lifts the letters off the line and keeps their shape.
API Reference
StretchText
<span> data-slot="stretch-text"
textstring
The text. Its line breaks (\n) are kept.
duration?number
One round: a letter's squash and stretch and the rest after it, in milliseconds. The squash and stretch take the first two fifths.
- Default
2000
intensity?"subtle" | "medium" | "strong"
How far each letter squashes and stretches. @default "medium".
- Type
"subtle" | "medium" | "strong"
loop?boolean
Whether it keeps going; false plays one round, when the page shows
it.
- Default
true
stagger?number
The time between one letter squashing and the next, in milliseconds.
- Default
80
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
Forwarded to the part.
--stretch-text-amountstring
How much a letter squashes (0.25, a quarter of its height).
--stretch-text-durationstring
One round, squash, stretch and rest (2s).
--stretch-text-staggerstring
The time between one letter squashing and the next (80ms).
Related
- Pro
Bouncing Text
MotionLetters that leap off the line
- Pro
Wobble Text
MotionLetters that rock in place
- Pro
Waveform Text
MotionA quick wave, loudest in the middle
- Pro
Pop Text
EntranceLetters that spring in past their size
- Pro
Elastic Text
InteractiveLetters stretch as the pointer passes
- Pro
Text Pressure
InteractiveWidth that follows the pointer