Kinetic Morph Text
Letters lift, rotate, and reshape into the next phrase with delicate outline trails
$ pnpm dlx shadcn@latest add @remocn/kinetic-morph-textUsage
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"
/>| Prop | Type | Default | Description |
|---|---|---|---|
text | string | "Hello | Make it move | Shape what's next" | Phrases separated by pipes or newlines |
fontSize | number | 100 | Maximum font size; automatically reduced to fit the longest phrase |
fontWeight | number | 600 | CSS font weight |
color | string | "#b4f4d9" | Letter and outline color |
backgroundColor | string | "#a800b7" | Full-frame background; accepts transparent |
spread | number | 180 | Flight radius in pixels, capped to fit the composition |
rotation | number | 110 | Maximum letter rotation in degrees |
morph | number | 0.75 | Soft shape-blend strength from 0 to 1 |
trails | number | 0.45 | Outline echo opacity from 0 to 1 |
transitionFrames | number | 54 | Entrance and transition duration at 30 fps |
holdFrames | number | 42 | Readable pause per phrase at 30 fps |
loop | boolean | false | Start on the first phrase and cycle back to it |
speed | number | 1 | Playback multiplier; 0 freezes the animation |
className | string | — | Optional class name on the full-frame root |