What an Apple-style scroll animation is
The effect has a few names: scroll-scrubbed animation, image sequence animation, scrollytelling. They all describe the same thing. A short animation is exported as a numbered sequence of images, say frame_0000.jpg to frame_0119.jpg. The page pins a full-screen canvas behind the content. As the visitor scrolls, the page works out how far down they are, as a number from 0 to 1, and draws the matching frame.
Nothing plays on a timer. If the visitor stops, the picture stops. If they scroll back up, it reverses. That direct control is why it feels more like handling an object than watching a clip, and it is why product pages use it to show something from every side.
How it works, step by step
- Make the frames. Render an animation from 3D software, or take frames out of a video. 120 frames at 1280 pixels on the long edge is a reasonable starting point.
- Preload them. Every frame has to be in memory before it is needed, or the canvas shows a gap while the image downloads. A good approach loads every fifth frame first so the whole range is roughly covered, then fills in the rest.
- Map scroll to a frame. Progress is
scrollYdivided by the scrollable distance (page height minus window height). Multiply by the frame count minus one and round. - Draw on the next animation frame. Scroll events fire faster than the screen repaints. Wrap the draw in
requestAnimationFrameso it runs at most once per repaint. - Cover the screen. Scale each image so it fills the canvas and crop the overflow, the same way
object-fit: coverdoes for an image.
How to make a scroll animation website without code
ScrollCraft is a free, open-source builder that does every step above for you and hands you the finished site as plain files.
- Pick a starting point. Choose one of 23 templates, each a finished site with its own scroll background, or describe your business in a paragraph and the AI writer drafts the whole site for you.
- Choose the background.Keep the template's drawn background (Gradient Flow, Geometric, Particles or Wave, in your colours) or upload your own video and its frames are taken out in your browser.
- Edit the words. Change headings, text and buttons in the editor and watch the preview scroll.
- Export. Download a ZIP with
index.html, your frames if you used a video, and a README that explains how to put it online for free. No account is needed for any of this.
A drawn background ships no images at all. The exported page carries the drawing code and redraws each frame at the visitor's screen size, so the page itself comes to about 30 KB. See what the export contains for the full list of files.
How to build an image sequence scroll animation in HTML and JavaScript
If you would rather write it yourself, this is the whole idea in about forty lines. Put your frames in a frames folder beside the page.
<canvas id="seq"></canvas>
<div style="height: 400vh"></div>
<script>
const canvas = document.getElementById("seq");
const ctx = canvas.getContext("2d");
const count = 120;
const frames = [];
for (let i = 0; i < count; i++) {
const img = new Image();
img.src = `frames/frame_${String(i).padStart(4, "0")}.jpg`;
frames.push(img);
}
function draw(index) {
const img = frames[index];
if (!img.complete || !img.naturalWidth) return;
canvas.width = innerWidth;
canvas.height = innerHeight;
const s = Math.max(canvas.width / img.naturalWidth, canvas.height / img.naturalHeight);
const w = img.naturalWidth * s, h = img.naturalHeight * s;
ctx.drawImage(img, (canvas.width - w) / 2, (canvas.height - h) / 2, w, h);
}
let ticking = false;
addEventListener("scroll", () => {
if (ticking) return;
ticking = true;
requestAnimationFrame(() => {
const max = document.documentElement.scrollHeight - innerHeight;
const p = Math.min(Math.max(scrollY / max, 0), 1);
draw(Math.round(p * (count - 1)));
ticking = false;
});
}, { passive: true });
frames[0].onload = () => draw(0);
</script>And one line of CSS to pin the canvas behind everything else:
#seq { position: fixed; inset: 0; width: 100%; height: 100%; z-index: -1; }That is enough to see the effect. A production version needs more: it should size the canvas for the device pixel ratio (capped at 2, or a phone ends up drawing millions of pixels each frame), only resize the canvas when the window changes rather than on every draw, preload in a sensible order, and show something useful if the frames fail to load. The exported ScrollCraft page does all of that, and since it is plain JavaScript you can open it and read how.
Performance on mobile
- Weight. 120 JPEGs at 1280 pixels can easily add up to several megabytes. Lower the frame count or the JPEG quality before anything else.
- Portrait screens. A landscape frame on a tall phone is mostly cropped away. A separate portrait set, cut for phones, looks better. ScrollCraft can make one from an uploaded video and serves it below 768 pixels wide.
- Decode off the scroll path. Call
img.decode()after each frame loads so the browser does not stall decoding a JPEG in the middle of a scroll. - Keep text readable. Moving pictures behind words make the words harder to read. A dark overlay or a panel behind the text fixes that.
Reduced motion and accessibility
Some people set their system to reduce motion because animation makes them unwell. A scrubbed background only moves when the visitor scrolls, which is gentler than autoplay, but any extra entrance animations should switch off under prefers-reduced-motion: reduce. ScrollCraft's exported pages turn their text reveal animations off for those visitors. Mark the canvas aria-hidden if it is decoration, and keep every piece of real information in the text, not in the frames.
The demo at the top of this page follows the same rule: with reduced motion on, it stops following the scroll and gives you a slider instead.