shadcn.io is not affiliated with official shadcn/ui
Ripple Text turns a line into the surface of a pond. Press a letter and a wave runs out from it to both ends of the text: each letter bobs up and settles a beat after its neighbour, a little lower the further the wave has come. Press again, anywhere, and a fresh wave starts from there.
Use it for a playful headline, a 404 page or a title that should answer a tap. For a wave that rolls on its own, use Wave Text; for a ripple on a button, Ripple Button. A press writes the letter's place to a CSS variable and restarts a CSS keyframe animation the install adds to your stylesheet, delayed on each letter by its distance from that place: no state, no animation library and no frame loop. With reduced motion the letters stay put.
Installation
Usage
import { RippleText } from "@/components/ui/ripple-text";<h1>
<RippleText text="Make a splash" />
</h1>Demos
Intensity
intensity is how high the first crest lifts the letter pressed: subtle, medium (the default) or strong. Further out the wave is lower, never under a quarter of that.
Timing
stagger is the time the wave takes from one letter to the next, 45 ms by default, so a lower value runs it faster; duration is how long one letter takes to bob and settle, 900 ms.
Accessibility
Screen readers read the text once, from a visually hidden copy, never letter by letter. The ripple is decoration: it answers the pointer only, has no stop in the tab order and changes nothing, so keyboard and screen reader users miss nothing, and the letters are back on their line within a second. With reduced motion a press does nothing.
FAQ
How does the wave travel?
Each letter knows its place in the text. A press writes the pressed letter's place to a CSS variable, and each letter's bob starts after its distance from that place times stagger. Flipping a data-wave attribute between two names restarts the bob on every letter at once, so a second press starts a fresh wave from wherever it lands.
Does it ripple across lines?
The wave runs along the text in reading order, so on wrapped text it carries from the end of one line to the start of the next, more like a wave along a rope than rings on water.
API Reference
RippleText
<span> data-slot="ripple-text"
textstring
The text.
duration?number
How long one letter takes to bob and settle, in milliseconds. @default 900.
intensity?"subtle" | "medium" | "strong"
How high the wave lifts the letters. @default "medium".
- Type
"subtle" | "medium" | "strong"
stagger?number
The time the wave takes from one letter to the next, in milliseconds: lower runs it faster.
- Default
45
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.
data-index?string
Mirrors index.
--ripple-text-durationstring
One letter's bob (900ms).
--ripple-text-heightstring
How high the first crest lifts a letter (0.3em).
--ripple-text-staggerstring
The time the wave takes from one letter to the next (45ms).
Related
- Pro
Wave Text
MotionAn endless swell, no click needed
- Pro
Liquid Text
InteractiveLetters that melt into each other
- Pro
Waveform Text
MotionA quick wave, loudest in the middle
- Pro
Pendulum Text
InteractiveLetters that swing as you pass
- Pro
Bouncing Text
MotionLetters hopping in turn, then resting
- Pro
Gravity Text
MotionLetters that fall on a click