13

Camera Moves

Push, pan, parallax, orbit — not Ken Burns.

Product heroes often "animate" by slowly zooming a flat screenshot. That is Ken Burns, and it reads as filler. A real camera move changes the relationship between layers: push-in, pan, parallax, or a shallow orbit.

Switch the modes and replay.

Flat is scale alone — the wrong default. Push moves toward the subject (scale + implied Z). Pan slides the frame. Parallax lets near and far layers travel at different rates. Orbit tips the card in 3D so you feel a viewpoint, not a resize.

Pick one job

One camera move per beat. A hero that pans and orbits and parallaxes is noise. Use push when you want commitment (CTA, feature deep-dive). Use parallax when you have real layers. Use orbit sparingly for product chrome that benefits from a sense of volume.

Keep durations long enough to read (2–3s for a hero loop) and easings gentle. Camera moves are atmosphere, not feedback — they should never compete with a click.

Usage

import { motion } from "motion/react";

{/* Push-in */}
<motion.div
    style={{ perspective: 900 }}
    animate={{ scale: [0.94, 1.05], z: [0, 40] }}
    transition={{ duration: 2.4, ease: [0.23, 1, 0.32, 1] }}
>
    <Card />
</motion.div>

{/* Parallax — different x on each layer */}
<motion.div animate={{ x: [-12, 12] }} transition={{ duration: 2.6 }}>
    <FarLayer />
</motion.div>
<motion.div animate={{ x: [-4, 4] }} transition={{ duration: 2.6 }}>
    <NearLayer />
</motion.div>
.stage {
    perspective: 900px;
}

@keyframes push {
    from { transform: translateZ(0) scale(0.94); }
    to { transform: translateZ(40px) scale(1.05); }
}

@keyframes orbit {
    from { transform: rotateY(-16deg) rotateX(8deg); }
    to { transform: rotateY(16deg) rotateX(4deg); }
}

.hero {
    animation: push 2.4s cubic-bezier(0.23, 1, 0.32, 1) alternate infinite;
}

Prefer transform and perspective over animating width, top, or background-size. Those are the difference between a camera and a stretch.