Skip to content
WANCRAFT

C.73Typography & Text

Morph Text

Words that melt into one another through a liquid blur-and-threshold morph.

NewReactSVGCSSTailwindintermediate

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 verified

Uses 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.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/morph-text.tsx.
  3. 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.

example.tsx
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

PropTypeDefaultDescription
wordsstring[]["Craft", "Motion", "Detail", "Intent"]Words or short phrases to cycle through, in order.
as"span" | "p" | "h1" | "h2" | "h3" | "div""span"Element to render.
morphTimenumber1000Duration of one morph, in ms.
cooldownTimenumber1800How long each word holds before the next morph, in ms.
blurnumber8Blur strength of the morph; higher melts the letterforms further.
thresholdnumber140Alpha cut-off of the threshold filter (1–254); lower values make thicker liquid bridges.
pausedbooleanfalseHold 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.
...propsHTMLAttributes—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
motion · continuousmotion · tweeninput · viewport

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.