Scroll Product Story
Use this for cinematic landing-page scenes where scrolling controls a product, object, vehicle, render, or other persistent visual while copy changes around it. Do not use it for ordinary entrance animations or decorative parallax.
Choose the renderer before tuning motion
- Use an image sequence drawn on a DPR-capped canvas when the object must scrub precisely forward and backward. This is the dependable choice for iPhone/iPad WebKit.
- A paused
<video>withcurrentTimeseeks is acceptable only after it has been tested on the actual target Safari environment. Do not treat desktop Chromium success as proof for iOS. - A real 3D model can use WebGL/Three.js if it materially improves the scene. Do not fake rotation with CSS transforms on a still image.
- Keep an accessible static representative frame for reduced-motion and no-JavaScript states.
Image-sequence baseline
- Render enough evenly spaced WebP/AVIF frames for the source motion. For a short rotating product clip, begin around 120–150 frames; 20–60 frames commonly reads as stepping once the object is large on screen.
- Load frames before starting the pinned story. Show a restrained loading state with real progress; never reveal a blank canvas.
- Draw frames to one canvas, cap DPR at 2, and redraw after a debounced resize. Use cover or contain deliberately; do not let the browser’s default sizing decide the crop.
- During loading or partial-cache operation, draw the nearest available frame rather than showing empty space.
- Let one normalized GSAP/ScrollTrigger timeline drive frame index, copy visibility, object scale/crop, and progress. The user must be able to scroll backward through the exact same states.
- Keep mobile composition independent: use the same sequence if suitable, but choose its own crop, copy positions, and shorter pinned distance. Do not force a desktop layout onto a phone.
Motion and composition
- The object should be a continuous physical presence; text leaves before or while the object moves, and incoming copy uses the space released by it.
- Use transform and opacity for overlays. Avoid bounce, elastic easing, independent step animations, and multiple competing scroll controllers.
- Verify that overlays do not cover the object unintentionally at the key beats. Large editorial type may overlap only as a deliberate art-direction choice.
Debugging order
- Add a diagnostic URL or local panel only when the issue cannot be reproduced. Capture renderer, ready state, decoded frames, current frame/time, events, scroll updates, and reduced-motion state.
- Diagnose the complete path: media loading, decode, canvas draw, stacking/crop, and ScrollTrigger updates. A changed
currentTimedoes not prove a video frame has been rendered. - After two failed video-scrub hypotheses on iOS, switch to canvas image sequence instead of layering more video fallbacks.
- Remove diagnostic UI from the normal URL after the issue is resolved; retain it only behind an explicit query parameter when useful.
Validation
- Check real device or iOS WebKit at the target viewport, including reverse scroll and loading from a cold cache.
- Check desktop and mobile separately for crop, text collisions, first-frame visibility, scroll release, and reduced motion.
- Run the repository’s typecheck, tests, and production build before publishing. Do not claim the motion is fixed based only on code compilation.