Perspective Marquee
A 3D-tilted infinite marquee with depth-of-field blur on items rolling toward the horizon.
A typography primitive that takes the seamless modulo-based loop from InfiniteMarquee and tilts it in 3D space using CSS perspective and rotateX/Y. Items further from the viewport center receive progressively heavier filter: blur() and lower opacity, mimicking depth of field. Edge vignettes fade the marquee into the background so the loop is invisible.
Installation
$ pnpm dlx shadcn@latest add @remocn/perspective-marqueeUsage
// src/Root.tsx
import { Composition } from "remotion";
import { PerspectiveMarquee } from "@/components/remocn/perspective-marquee";
const PerspectiveMarqueeScene = () => (
<PerspectiveMarquee
items={["Vercel", "Linear", "Stripe", "Figma"]}
rotateY={-28}
pixelsPerFrame={2}
/>
);
export const RemotionRoot = () => (
<Composition
id="PerspectiveMarquee"
component={PerspectiveMarqueeScene}
durationInFrames={240}
fps={30}
width={1280}
height={720}
/>
);Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | string[] | ["Vercel", "Linear", "Stripe", "Figma", "Notion", "Raycast", "Arc", "Cursor"] | Items rendered in the marquee. Repeated three times under the hood for a seamless loop. |
fontSize | number | 84 | Font size in pixels. |
color | string | "#fafafa" | Text color of each item. |
fontWeight | number | 700 | CSS font-weight. |
pixelsPerFrame | number | 2 | Horizontal scroll speed in pixels per frame. |
rotateY | number | -28 | Y-axis rotation in degrees applied to the marquee row. |
rotateX | number | 8 | X-axis rotation in degrees applied to the marquee row. |
perspective | number | 1200 | CSS perspective in pixels on the parent. |
fadeColor | string | "#050505" | Color used in the edge vignette gradients. |
background | string | "#050505" | Root container background color. |
speed | number | 1 | Playback speed multiplier. |
className | string | — | Optional className passed to the root container. |
Notes
Slow is hypnotic
Keep pixelsPerFrame between 1 and 3. The 3D tilt amplifies perceived speed — anything faster reads as motion sickness.
Match `fadeColor` to `background`
The vignette assumes fadeColor === background. If they differ you will see hard edges where the marquee ends and the background begins.