1 min readNext.jsCanvasPerformance
Why I rebuilt my portfolio as a scroll-driven film
Written by Nethma DissanayakeOnline Store Builder1 min read
Eighty-nine WebP frames, one canvas, zero video tags. Notes on building a scrollytelling hero that stays smooth on a phone.
Most portfolio heroes are a looping video. Mine is an image sequence scrubbed by scroll — the same technique Apple uses on product pages — because it gives deterministic frames, no autoplay restrictions, and a direct link between the visitor's hand and what they see.
The moving parts
- A 500vh scroll zone with a sticky, full-viewport
<canvas> - 89 frames pre-decoded into memory (frame 0 first, then six-wide concurrency)
- Scroll progress → integer frame index → one
drawImageper changed frame, coalesced throughrequestAnimationFrame
What I'd tell past me
- Reset your rAF handle in the effect cleanup, or StrictMode will silently stop every repaint.
- A portrait frame on an ultra-wide monitor needs a contain-over-blur fallback, not
object-fit: cover. - Version your frame URLs — browsers are happy to keep serving last week's sequence.
More on the Lenis + Framer Motion setup in a follow-up.


