Everything on this page is static files on a CDN — frames, one spritesheet, three hold loops and a pan schedule. There is no server, no database and no build step. That is deliberate: the library takes a list of URLs, and where they come from is your business.
A 2.8 MB spritesheet makes it scrollable in a second; full-resolution frames stream in behind it and cover as they land.
At frames 1, 61 and 150 the sequence pins and a short loop plays on top. Ping-pong, so there is no seam to hide.
On a phone, a keyframe schedule moves the crop window so a 16:9 frame
survives a 9:16 viewport. A few hundred bytes, no second asset set.
Open this page on a phone — or narrow the window
past 768 px — for a Fit / Fill / Follow switch that
shows the three ways to resolve the crop.
~530 lines of JavaScript. No framework, no canvas, no build. Scroll never touches framework state.
npm install scroll-frame-sequence
The source, the Python tools that turn a video into these frames, and a page of the numbers we estimated wrong are all on GitHub.