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.

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

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

tsx
<KineticMorphText
  text="Create | Iterate | Ship"
  spread={140}
  rotation={80}
  morph={0.65}
  trails={0.3}
  color="#ded4ff"
  backgroundColor="#171324"
/>

Props14

PropTypeDefault
text
string"Hello | Make it move | Shape what's next"

Phrases separated by pipes or newlines

fontSize
number100

Maximum font size; automatically reduced to fit the longest phrase

fontWeight
number600

CSS font weight

color
string"#b4f4d9"

Letter and outline color

backgroundColor
string"#a800b7"

Full-frame background; accepts transparent

spread
number180

Flight radius in pixels, capped to fit the composition

rotation
number110

Maximum letter rotation in degrees

morph
number0.75

Soft shape-blend strength from 0 to 1

trails
number0.45

Outline echo opacity from 0 to 1

transitionFrames
number54

Entrance and transition duration at 30 fps

holdFrames
number42

Readable pause per phrase at 30 fps

loop
booleanfalse

Start on the first phrase and cycle back to it

speed
number1

Playback multiplier; 0 freezes the animation

className
string—

Optional class name on the full-frame root

  • textstring

    Phrases separated by pipes or newlines

    Default"Hello | Make it move | Shape what's next"

  • fontSizenumber

    Maximum font size; automatically reduced to fit the longest phrase

    Default100

  • fontWeightnumber

    CSS font weight

    Default600

  • colorstring

    Letter and outline color

    Default"#b4f4d9"

  • backgroundColorstring

    Full-frame background; accepts transparent

    Default"#a800b7"

  • spreadnumber

    Flight radius in pixels, capped to fit the composition

    Default180

  • rotationnumber

    Maximum letter rotation in degrees

    Default110

  • morphnumber

    Soft shape-blend strength from 0 to 1

    Default0.75

  • trailsnumber

    Outline echo opacity from 0 to 1

    Default0.45

  • transitionFramesnumber

    Entrance and transition duration at 30 fps

    Default54

  • holdFramesnumber

    Readable pause per phrase at 30 fps

    Default42

  • loopboolean

    Start on the first phrase and cycle back to it

    Defaultfalse

  • speednumber

    Playback multiplier; 0 freezes the animation

    Default1

  • classNamestring

    Optional class name on the full-frame root