2.18 · Animation

Image Sequence Scrub.

Pre-rendered frames of a 3D object played back frame-by-frame as you scroll. Apple AirPods Pro silicone tip rotation, every car configurator, every "explore the inside" page.

What it is

Instead of doing real-time 3D in WebGL, designers pre-render an object as 30–120 image frames (one per few degrees of rotation, or one per phase of an animation), then scrub through them as the user scrolls. The result feels like buttery-smooth 3D but is just images. It's how Apple's product pages play those "rotate the AirPods Pro" or "watch the iPhone unfold" sequences — and how every car configurator lets you spin the car.

How it works

Two implementations: (1) Stack all frames as position: absolute divs with opacity: 0, then on scroll set only the active frame's opacity to 1. Cheap, works for ~30 frames. (2) Production-grade: a <canvas> + JS that calculates which frame index matches the current scroll progress and calls ctx.drawImage(frames[i], 0, 0). Preload all frames before the section enters view. Apple's AirPods Pro page uses ~150 JPG frames totaling ~5MB.

Pre-rendered framesEach frame = one moment in the animation (rotation, zoom, fold, etc.)
scroll progress → frame indexfloor(progress * frameCount) selects which frame to show
canvas vs stacked imgCanvas scales better for 60+ frames; stacked img is easier for prototypes
Preload everythingFrames must be loaded before the section enters view or playback stutters

Live demo

Scroll inside. The orb rotates 360° — each scroll frame swaps to a different rendered angle. (24 simulated frames using CSS gradients.)

Live · scroll inside
↓ scroll to rotate
Frame 01 / 24

Rotate it 360°.

24 frames · scroll-scrubbed playback

— end —

Copy this prompt

Prompt · 2.18 Image Sequence
Build a scroll-driven image sequence "scrubber" that plays back a 3D rotation frame-by-frame. Tall outer container with overflow-y:scroll containing a sticky pin (position:sticky top:0 height:100vh) inside an 1800px-tall section. Inside the pin: a 320×320 stage holding 24 absolutely-positioned circular frames stacked on top of each other (all inset:0, border-radius:50%, opacity:0 default, opacity:1 when .on). Each frame represents an angular step of a rotating 3D object — for the demo, generate them via CSS background gradient strings parameterized by angle (use document.createElement in JS), each frame's background is a radial-gradient highlight at a position based on cos/sin of the angle + a linear-gradient body — together they simulate a sphere rotating. JavaScript: on scroll, calculate the section's scroll progress (0 to 1) and pick frame index = floor(progress * 24). Toggle .on between frames. Update a "Frame N / 24" counter and a 180px progress bar. Add a soft shadow ellipse below the stage. Production version: replace generated frames with <img> tags preloaded from your rendered sequence (or use canvas + ctx.drawImage for >30 frames).

Example sites to study