# Zoom Words
URL: https://remocn.dev/docs/typography/zoom-words

Huge words fade into a long line while the camera rides the write head

- Install: `npx shadcn@latest add @remocn/zoom-words`
- Vibe: premium
- Natural length: 63f @ 30fps

## Installation

```bash
npx shadcn@latest add @remocn/zoom-words
```

## Usage

The first word fades in centered and the camera holds still. The whole phrase then reveals on one clock with a short gentle ramp-up settling into constant speed — the measured profile of the reference — with each word sliding in on a small diagonal, lightly softened but always readable, while the camera rides the growing line and stops with the last word centered. The shot starts `blur` em out of focus and sharpens over `blurFrames`. Meant to be hard-cut into the next scene (in the reference, a typewriter scene follows the cut).

```tsx
// src/Root.tsx
import { Composition } from "remotion";
import { ZoomWords } from "@/components/remocn/zoom-words";

const ZoomWordsScene = () => (
  <ZoomWords text="Still piecing together tools" />
);

export const RemotionRoot = () => (
  <Composition
    id="ZoomWords"
    component={ZoomWordsScene}
    durationInFrames={75}
    fps={30}
    width={1280}
    height={720}
  />
);
```

### With Backdrop

The component renders transparent — supply the background via `Backdrop`. The reference pairs it with a dark-to-violet vertical gradient.

```tsx
import { Composition } from "remotion";
import { ZoomWords } from "@/components/remocn/zoom-words";
import { Backdrop } from "@/components/remocn/backdrop";

const ZoomWordsScene = () => (
  <Backdrop
    fill={{
      type: "gradient",
      value: "linear-gradient(180deg, #0a0612 25%, #6a3fd6 100%)",
    }}
  >
    <ZoomWords text="Still piecing together tools" />
  </Backdrop>
);

export const RemotionRoot = () => (
  <Composition
    id="ZoomWords"
    component={ZoomWordsScene}
    durationInFrames={75}
    fps={30}
    width={1280}
    height={720}
  />
);
```

### Syncing

The exported `zoomWordsLength(text, wordGap)` helper returns the frame on which the camera settles after the last word — cut to the next scene at or shortly after it.

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `text` (required) | `string` | — | The phrase to reveal; it may be arbitrarily long |
| `wordGap` | `number` | `12` | Frames between word reveals |
| `fontSize` | `number` | `64` | Base font size in pixels before the camera zoom |
| `zoom` | `number` | `2.2` | Camera scale applied to the whole shot |
| `anchor` | `number` | `0.5` | Horizontal fraction of the frame the camera holds — the first word appears centered on it |
| `blur` | `number` | `0.04` | Starting defocus in em, sharpening to zero over blurFrames |
| `blurFrames` | `number` | `60` | Frames the focus pull takes |
| `color` | `string` | `"#cfc2ff"` | Text color (any valid CSS color) |
| `fontWeight` | `number` | `400` | CSS font-weight |
| `className` | `string` | — | Optional className passed to the underlying span |

## Use when
- An intro should open uncomfortably close: huge words appearing one by one while the camera tracks the growing line off-frame.
- You want the shot to start slightly defocused and sharpen while the reveal runs — a cold-open feel before a hard cut.
- The phrase is long and should never need to fit the frame.

## Don't use when
- The whole phrase must fit the frame at rest — use `per-word-crossfade` or `word-stream`.
- You need character-by-character typing with a caret — use `typewriter`.
- The camera language should be a real 2.5D move over a scene rather than a text close-up — use `stage`.
- One spoken word at a time from a voiceover — use `caption-word-pop`, which follows the transcript timing.