Text Effects
GlyphWave
A soft wave runs through the letters again and again, each letter rising and settling just after the one before.
Download
- React
- Tailwind CSS v4
- motion
components/ui/glyph-wave.tsx
"use client";
import { motion, useReducedMotion } from "motion/react";
type GlyphWaveProps = {
text: string;
className?: string;
/** How high each letter rises, in em. */
height?: number;
/** Seconds between one letter and the next. */
stagger?: number;
/** Seconds of rest before the wave runs again. */
rest?: number;
};
/* GlyphWave: a soft wave runs through the letters again and again, each letter rising and settling just after the one before. */
export function GlyphWave({ text, className = "", height = 0.2, stagger = 0.05, rest = 1.2 }: GlyphWaveProps) {
const reduce = useReducedMotion();
if (reduce) return <span className={className}>{text}</span>;
const words = text.split(" ");
// Each letter's place in the whole text, so the wave carries on across words.
const starts = words.map((_, w) => words.slice(0, w).join("").length);
return (
<span className={className}>
<span className="sr-only">{text}</span>
<span aria-hidden>
{words.map((word, w) => (
<span key={w}>
<span className="inline-block whitespace-nowrap">
{[...word].map((ch, i) => (
<motion.span
key={i}
className="inline-block"
animate={{ y: ["0em", `-${height}em`, "0em"] }}
transition={{ duration: 0.6, ease: "easeInOut", repeat: Infinity, repeatDelay: rest, delay: (starts[w] + i) * stagger }}
>
{ch}
</motion.span>
))}
</span>
{w < words.length - 1 && " "}
</span>
))}
</span>
</span>
);
}
1. Install the dependency.
npm i motion2. Paste the Code tab into
components/ui/glyph-wave.tsx. The styles are Tailwind CSS v4 classes.3. Use it. This is the preview above:
app/glyph-wave-demo.tsx
import { GlyphWave } from "@/components/ui/glyph-wave"; export default function GlyphWaveExample() { return ( <div className="grid h-full place-items-center bg-[radial-gradient(circle_at_50%_60%,#1d1a33,#0d0c14_70%)] p-6"> <GlyphWave text="Riding the wave" className="text-center text-[clamp(32px,6vw,64px)] font-bold tracking-tight text-[#ede9fe]" /> </div> ); }
Props
| Name | Type | Default | What it does |
|---|---|---|---|
| text | string | — | Text to show. |
| height | number | 0.2 | How high each letter rises, in em. |
| stagger | number | 0.05 | Seconds between letters. |
| rest | number | 1.2 | Seconds of rest before the next wave. |
| className | string | "" | Type styles for the text. |