Kinetic Morph Text

Letters lift, rotate, and reshape into the next phrase with delicate outline trails

Installation
$ pnpm dlx shadcn@latest add @remocn/kinetic-morph-text

Usage

Separate phrases with | or a newline. The first phrase flies into place; after a readable pause, its letters lift and rotate into the next phrase. Identical letters travel to their new positions. Other letters stretch and soften into replacement glyphs, while additional characters enter and excess characters leave. The final phrase stays on screen.

import { KineticMorphText } from "@/components/remocn/kinetic-morph-text";
 
export const TitleScene = () => (
  <KineticMorphText text="Hello | Make it move | Shape what's next" />
);

The soft morph combines squash/stretch and a local blur/threshold blend of native glyphs; it does not interpolate font outlines. Contour trails sample earlier poses and disappear when the letters settle. All motion is driven by the Remotion frame, including when scrubbing backward.

Timing

At the defaults, the first entrance takes 54 frames, followed by a 42-frame hold. Each subsequent phrase adds another 54-frame transition and 42-frame hold. The three-phrase sequence finishes moving at frame 246; its full duration including the final hold is 288 frames at 30 fps.

Use the duration helper when changing the phrase count, timing, or speed. It returns frames at 30 fps; scale the result for another composition frame rate. The docs preview updates its duration automatically when the copy, timing, or speed changes, so every phrase remains included.

import { Composition } from "remotion";
import {
  KineticMorphText,
  getKineticMorphTextDuration,
} from "@/components/remocn/kinetic-morph-text";
 
const props = {
  text: "Think | Make | Move | Repeat",
  transitionFrames: 48,
  holdFrames: 36,
  speed: 1,
};
 
export const Root = () => (
  <Composition
    id="KineticMorphText"
    component={KineticMorphText}
    defaultProps={props}
    durationInFrames={getKineticMorphTextDuration(props)}
    fps={30}
    width={1280}
    height={720}
  />
);

With loop, the sequence starts on the readable first phrase, skips the initial entrance, and uses its final transition to return to that phrase. One complete cycle has the same duration as the non-looping sequence. A single phrase stays still in loop mode.

Tuning the motion

Reduce spread and rotation for quieter movement. Set morph={0} for a clean glyph crossfade during the flight and trails={0} to remove the outlines. The font is Arial with Helvetica and sans-serif fallbacks, so no font download is needed. The longest phrase determines a shared font size that fits within 82% of the composition width. Empty entries are ignored; empty input renders only the background. Spaces, punctuation, repeated letters, and grapheme clusters are preserved.

<KineticMorphText
  text="Create | Iterate | Ship"
  spread={140}
  rotation={80}
  morph={0.65}
  trails={0.3}
  color="#ded4ff"
  backgroundColor="#171324"
/>
Props
PropTypeDefaultDescription
text
string"Hello | Make it move | Shape what's next"Phrases separated by pipes or newlines
fontSize
number100Maximum font size; automatically reduced to fit the longest phrase
fontWeight
number600CSS font weight
color
string"#b4f4d9"Letter and outline color
backgroundColor
string"#a800b7"Full-frame background; accepts transparent
spread
number180Flight radius in pixels, capped to fit the composition
rotation
number110Maximum letter rotation in degrees
morph
number0.75Soft shape-blend strength from 0 to 1
trails
number0.45Outline echo opacity from 0 to 1
transitionFrames
number54Entrance and transition duration at 30 fps
holdFrames
number42Readable pause per phrase at 30 fps
loop
booleanfalseStart on the first phrase and cycle back to it
speed
number1Playback multiplier; 0 freezes the animation
className
stringOptional class name on the full-frame root