Parallax Layers
Depth-offset planes driven by one camera move. Install with npx remotion-ui@latest add parallax-layers.
PrimitivePrimitives
$ npx remotion-ui@latest add parallax-layersPlanes at different depths, moving at different rates, on one driver.
import { ParallaxLayers } from "@/remotion/primitives/parallax-layers";
<ParallaxLayers
travel={420}
layers={[
{ content: <Sky />, depth: 0.2, blur: 2 },
{ content: <Headline />, depth: 0.55 },
{ content: <Foreground />, depth: 1, blur: 8 },
]}
/>Where it sits
Multi-layer, unlike zoom-pan-frame, which moves a camera over a single still.
The split matters because parallax is a relationship: the illusion comes from
planes moving at different rates against each other, so one driver has to feed
all of them. Animating three layers separately gets you three animations that
happen to overlap.
Depth
depth is the only number a caller has to think about. A plane at depth={0}
is the focal plane and never moves; everything else is offset by
depth × travel relative to it. Negative depths move the other way, which is
what an element in front of the lens does.
Layers are listed back to front, and a layer with no depth gets one from its
position in the list, so the simplest call is just an ordered array.
The sweep
The move runs from -0.5 to 0.5 rather than 0 to 1, so the middle of the window is the layout you actually composed and the planes are offset in both directions around it. A sweep that started in frame and slid out would mean designing against a position nobody sees.
zoom adds scale to the nearer planes as they travel, which is the difference
between a dolly and a pan and the half people forget.
Drive it from the frame — startAtInFrames, durationInFrames, motion — or
pass progress and drive it from a scroll position, a spring, or a scene's own
clock.
Multi-layer, unlike `zoom-pan-frame`, which moves a camera over one still. Parallax is a relationship, so one driver feeds every plane and `depth` is the only number a caller sets. The sweep runs -0.5 to 0.5, so the middle of the window is the layout you composed.
Agent notes
Install first, then import the copied source component locally. AI guide →
@/remotion/primitives/parallax-layers- Use when: frame-level motion primitives and reusable animation wrappers.
- Customize: layers, travel, angle, zoom, plus copied source for timing, layout, colors, and typography.
- Rule: do not import this component from the
remotion-uinpm package; it is copied into your project.
Usage
import { ParallaxLayers } from "@/remotion/primitives/parallax-layers";
<ParallaxLayers
travel={420}
layers={[
{ content: <Sky />, depth: 0.2, blur: 2 },
{ content: <Headline />, depth: 0.55 },
{ content: <Foreground />, depth: 1, blur: 8 },
]}
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| layers | ParallaxLayer[] | - | Back to front. Each is `{ content, depth, blur, opacity, scale }`; depth 0 is the focal plane, 1 travels furthest, negative travels the other way. |
| travel | number | 320 | Travel of a depth-1 plane across the whole move, in px. |
| angle | number | 0 | Direction of the camera move. 0 tracks right, 90 cranes down. |
| zoom | number | 0.12 | Extra scale the nearest plane picks up. 0 is a flat track. |
| progress | number | - | Drive the move yourself, 0-1. Overrides the frame-based sweep. |
| startAtInFrames | number | 0 | Frame the sweep starts on. |
| durationInFrames | number | the composition | Length of the sweep. |
| motion | "ease" | "linear" | "ease" | `ease` settles at both ends; `linear` is a constant-speed dolly. |
| backgroundColor | string | "#07080e" | Plate behind every plane. |