Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Wave Text for React

Text that rides a wave, each letter rising, sinking and tilting with the slope beneath it. For React with Base UI, when a headline should feel playful and never sit still.

Framework

Wave Text sets a line on a smooth, endless swell: each letter rises and sinks a little after its neighbour, so a wave rolls back through the text, and each one tilts with the slope beneath it, like a flag in a steady breeze.

Use it for a playful headline, a 404 page or a word in a hero that should feel alive. For a quicker wave that runs forward through the line like sound, use Waveform Text; for letters that hop in turn and rest, Bouncing Text; for letters that each float on their own, Drift Text. The motion is two CSS keyframe animations the install adds to your stylesheet, a rise and a tilt, started part way through by each letter's place in the wave, with no animation library. With reduced motion the text sits on its line.

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 { WaveText } from "@/components/ui/wave-text";
<h1>
  <WaveText text="Make some waves" />
</h1>

Demos

Intensity

intensity is how high the letters rise and how far they tilt: subtle for a ripple under body text, medium, the default, for a headline, strong for a word that should be the loudest thing on the page.

Preview width

Wavelength

wavelength is how many characters one wave spans, 8 by default: fewer make a short, choppy sea, more one long swell. duration is one full wave through a letter, 2000 ms by default; a short wave suits a quick one, a long wave a slow one.

Preview width

Accessibility

Screen readers read the text once, as plain text, from a visually hidden copy; the moving letters are hidden from them. Words wrap whole, and the line keeps its direction on a right-to-left page, where the letters tilt the other way to follow the slope. The letters move by a fraction of their own size, so the text stays readable at every moment. With reduced motion it doesn't move.

FAQ

How is it different from Waveform Text?

Wave Text is a slow swell that rolls back through the line, the letters tilting with it. Waveform Text is a quick vibration that runs forward, from the start of the line to its end, loudest in the middle and with no tilt, like sound on a meter.

Does the wave ever jump or restart?

No. Each letter runs a smooth half wave and back, over and over, and every letter is already part way through its wave when the page shows it, so there's no start and no seam.

Does the moving text push the page around?

No. The letters move with transforms, which never change the layout: the line keeps its size and the text around it stays put. Leave a little line height if the wave is strong, so the crests don't touch the line above.

Can I set the exact height or tilt?

Yes. Leave intensity out, which would set them, and set --wave-text-height (a length, such as 0.2em) and --wave-text-tilt (an angle, such as 0deg for no tilt) on the text, in its style or a class such as [--wave-text-tilt:0deg].

Does it work with every script?

With scripts whose letters stand apart, Latin, Cyrillic, Greek, Hebrew, CJK. Arabic letters join, and splitting a word into characters breaks the joins, so use it for short Latin words on an Arabic page instead.

What happens with reduced motion?

The wave stops and every letter sits on the line, upright.

API Reference

WaveText

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

PropType
textstring

The text. Its line breaks (\n) are kept.

duration?number

One full wave through a character, up, down and back, in milliseconds.

Default
2000
intensity?"subtle" | "medium" | "strong"

How high the letters rise and how far they tilt. @default "medium".

Type
"subtle" | "medium" | "strong"
wavelength?number

How many characters one wave spans: fewer make a choppier sea, more a long swell.

Default
8
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.

CSS variableType
--wave-text-durationstring

One full wave through a character (2s).

--wave-text-heightstring

How far a letter rises and sinks (0.12em).

--wave-text-tiltstring

A letter's steepest tilt (6deg).

--wave-text-wavelengthstring

How many characters one wave spans (8).

All 97 text effects