Overview
Morph Text cycles through a list of words. Two stacked copies cross-blur — the outgoing word dissolves while the next one condenses — and an SVG feColorMatrix alpha threshold snaps the blurred shapes back to hard edges, so the letterforms appear to flow into each other like liquid. Every word is laid out invisibly in the same grid cell, so the element is always as wide as the longest word and nothing around it reflows. One requestAnimationFrame loop drives the morph and pauses offscreen and in hidden tabs; screen readers get the full list once, and reduced motion swaps the liquid morph for a plain crossfade.
01Installation
Method 01 · Registry
CLI verifiedUses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/morph-text.tsx and adds its dependencies.
npx shadcn@latest add https://wancraft.my/r/morph-text.jsonMethod 02 · Copy and paste
- 1. No extra dependencies — React and Tailwind CSS only.
- 2. Copy the source from the Code tab into
components/ui/morph-text.tsx. - 3. Import it and adjust props.
- Dependencies
- None
- Peer
- react ≥ 18, tailwindcss ≥ 4
- Added
- 13 Oct 2026
- Updated
- —
02Usage
The default configuration. Change properties above to generate a tailored example in the Usage tab.
import { MorphText } from "@/components/ui/morph-text";
export function MorphTextExample() {
const words = ["Craft", "Motion", "Detail", "Intent"];
return (
<MorphText
words={words}
as="h2"
className="text-6xl font-semibold tracking-tight"
/>
);
}03Props
| Prop | Type | Default | Description |
|---|---|---|---|
| words | string[] | ["Craft", "Motion", "Detail", "Intent"] | Words or short phrases to cycle through, in order. |
| as | "span" | "p" | "h1" | "h2" | "h3" | "div" | "span" | Element to render. |
| morphTime | number | 1000 | Duration of one morph, in ms. |
| cooldownTime | number | 1800 | How long each word holds before the next morph, in ms. |
| blur | number | 8 | Blur strength of the morph; higher melts the letterforms further. |
| threshold | number | 140 | Alpha cut-off of the threshold filter (1–254); lower values make thicker liquid bridges. |
| paused | boolean | false | Hold the current word (e.g. wire it to a pause button). |
| align | "left" | "center" | "right" | "center" | Alignment of shorter words within the width of the longest. |
| ...props | HTMLAttributes | — | Forwarded to the root element. |
04Features
- 01Liquid morph: cross-blur plus an feColorMatrix alpha threshold
- 02Zero layout shift: the element reserves the width of the longest word
- 03Text colour comes from CSS (currentColor) — style it like any text
- 04rAF loop pauses offscreen, in hidden tabs and when paused
- 05Morph, hold, blur and threshold are all tunable
05Accessibility
- The animated layers are aria-hidden; a visually hidden span lists every word once, so screen readers do not hear a word change every few seconds.
- With prefers-reduced-motion the blur and threshold filter are removed and words change with a plain crossfade.
- The paused prop lets you offer a pause control for content that moves for more than five seconds (WCAG 2.2.2).
06Limitations
- The threshold filter hard-cuts anti-aliasing, so very small sizes look jagged; it is meant for display type.
- The text must be a solid colour: gradients or background-clip text do not survive the alpha threshold.