DEV Community

Cover image for Do scroll animations hurt SEO? A practical Core Web Vitals checklist for image-sequence pages
Alki
Alki

Posted on Originally published at beta.scrollsequence.com

Do scroll animations hurt SEO? A practical Core Web Vitals checklist for image-sequence pages

Apple-style scroll animations don't have to cost you rankings. Here's what Google actually sees, which Core Web Vitals they can break, and a checklist to keep an animated page fast and indexable.

Do scroll animations hurt SEO? A practical Core Web Vitals checklist for image-sequence pages

Under almost every "build a 3D scroll website in 10 minutes" video, someone asks the same thing:

"But what about SEO with all this animation?"

It's a fair worry. These pages often ship a few hundred images, a big canvas and a lot of JavaScript. The good news is that the animation itself is rarely what hurts rankings. What hurts is how it's built: text baked into frames, a huge hero that blocks the first paint, and layout that jumps around while frames load.

This post explains what Google actually sees on an image-sequence page and gives you a checklist you can run through before you publish.

What Google sees (and doesn't)

A scroll image sequence is usually a <canvas> with numbered frames drawn onto it as you scroll. To a search engine, that canvas is close to invisible: it can't read text or understand anything painted onto it.

That's fine, as long as the canvas is decoration and not your content. Problems start when:

  • Headlines and copy are inside the frames. If "The lightest headphones we've ever made" only exists as pixels in frame 0042, Google never reads it.
  • The whole page is one giant animation. No <h1>, no paragraphs, nothing to rank for.
  • Nothing is in the HTML until JavaScript runs. Google does render JavaScript, but it's slower and less reliable than plain HTML, and other crawlers and AI assistants often don't render it at all.

Rule of thumb: keep every word you want to rank for as real HTML text, layered on top of or next to the canvas. Use one <h1>, normal headings and paragraphs, and let the animation sit behind them.

The three Core Web Vitals an animation can break

Core Web Vitals are Google's page-experience metrics. Image-sequence pages can hurt all three if you're careless.

1. LCP (Largest Contentful Paint): the heavy hero

LCP measures how fast the biggest visible element appears. On animated pages, that's usually the first frame of the hero. If the browser has to wait for a script to start, then fetch frames, then draw on a canvas, LCP gets slow.

What helps:

  • Render the first (or current) frame immediately The visitor (and Google) sees a picture right away.
  • Don't let the frames compete with the hero. Start fetching the rest of the sequence after the page has loaded, or when the section gets close (more on that below).

2. CLS (Cumulative Layout Shift): the jumping page

CLS measures how much things move while the page loads. Animated sections often start at zero height, then grow once JavaScript measures them, and everything below jumps.

What helps:

  • Reserve the space up front. Give the canvas wrapper a fixed aspect-ratio (for example aspect-ratio: 16 / 9) or an explicit height in CSS, so the layout is final before any frame arrives.
  • Set the scroll length in CSS, not after load. If the pinned section is 300vh tall, write that in the stylesheet rather than calculating it in JS.
  • Watch out for iOS Safari's address bar. When it shows and hides, the viewport resizes. With GSAP, ScrollTrigger.config({ ignoreMobileResize: true }) stops it from recalculating and jumping mid-scroll. Scrollsequence handles this automatically.

3. INP (Interaction to Next Paint): the busy main thread

INP measures how quickly the page responds when someone taps or clicks. Decoding and drawing large frames on every scroll event can keep the main thread busy, so buttons feel sluggish.

What helps:

  • Draw inside requestAnimationFrame, and skip the draw when the frame index hasn't changed.
  • Do not decode ahead of time. await img.decode() (or createImageBitmap) just bloats memory and crashes tabs.
  • Cap the canvas resolution. On phones, limit it to a device pixel ratio of 2. Drawing at 3x on a large screen is a lot of pixels for very little visible gain.

Keep the total weight sane

Search engines don't penalise a page for being "big" as such, but heavy pages do worse on LCP and mobile, and real visitors bounce. Some realistic targets:

Typical AI-demo export A sane target
Format JPG, WebP or AVIF, about 75–80 quality
Frames 200–300+ 60–150
Width Full source size about 1600–1920px desktop, about 960px phones
Total Often 100+ MB Usually 5–15 MB

If you're starting from a video, ffmpeg gets you most of the way:

ffmpeg -i hero.mp4 -vf "fps=24,scale=1600:-1" -c:v libwebp -quality 78 frames/hero_%04d.webp
Enter fullscreen mode Exit fullscreen mode

Then make a smaller set for phones (narrower, and every other frame is usually enough).

Lazy-load the sequence, not the content

Load the frames only when the section is about to be seen. IntersectionObserver is the simplest way to do it: think of it as a doorbell that rings when the section comes near the screen.

const section = document.querySelector('.hero-sequence');

const io = new IntersectionObserver((entries) => {
  if (entries[0].isIntersecting) {
    loadFrames(); // your preload function
    io.disconnect();
  }
}, { rootMargin: '600px 0px' }); // start a bit before it's visible

io.observe(section);
Enter fullscreen mode Exit fullscreen mode

Two extra tips:

  • Load in passes. Fetch every 8th frame first so the animation is scrubbable immediately, then fill in the gaps while the visitor scrolls.
  • Never lazy-load your text. Only the frames should wait. Headings and copy belong in the initial HTML.

Accessibility helps too

Accessibility isn't a direct ranking factor, but it overlaps a lot with what search engines can understand:

Give the canvas role="img" and an aria-label describing what the animation shows, or mark it aria-hidden="true" if it's purely decorative and the text nearby says everything.

Pre-publish checklist

Run through this before you ship an animated page:

  • Every heading and sentence you care about is real HTML text, not pixels in a frame.
  • One <h1>, and a sensible heading structure under it.
  • The first (current) frame is shown immediately and is not hidden until animation is loaded.
  • The animation section has its size reserved in CSS (no layout jump).
  • Frames are WebP or JPG, 60–150 of them, total under about 15 MB.
  • There's a lighter frame set for phones.
  • Drawing happens in requestAnimationFrame and skips unchanged frames.
  • PageSpeed Insights on mobile shows LCP, CLS and INP in the green (or at least not red).

So, does it hurt SEO?

Not if the animation is decoration on top of a real page. Google ranks the text, structure and speed; it doesn't care that a pair of headphones spins while you scroll. Keep the words in HTML, keep the frames light and late, and an animated page can rank just like a static one.

Scrollsequence, a WordPress plugin (with a JS/React SDK in v2) for image-sequence scroll animations. It handles the frame optimisation, mobile frame set and progressive loading described above, so if you'd rather not wire it up by hand, that's an option. Everything in the checklist works without it, too.


Originally published on the Scrollsequence blog.

Top comments (0)