CODEXA.Technologiez
All insightsEngineering

Your animations are probably costing you Core Web Vitals

Codexa Engineering · Sep 16, 2026 · 3 min read

Scroll-triggered reveals are close to universal on modern marketing sites. Content starts invisible, then fades and rises into place as you scroll. Done well it looks considered.

It also has a failure mode that is easy to ship and hard to notice, because it never shows up on the machine you built it on.

The mechanism

A typical reveal renders its initial state on the server. That means the HTML arrives with the content already set to `opacity: 0`, waiting for JavaScript to animate it to visible.

Everything works if JavaScript loads, parses, hydrates and runs. Until then, the content is in the document and invisible on the screen.

Why the metric cares

Largest Contentful Paint measures when the biggest piece of content actually appears. Content sitting at zero opacity has not appeared.

So LCP is not measured from when your server responded. It is measured from after your JavaScript bundle has downloaded, parsed and hydrated — on the visitor's device, on the visitor's connection, which is slower than yours.

Google's thresholds are documented: 2.5 seconds or less is good, over 4 seconds is poor. A hero that cannot paint until hydration completes can cross that line on mid-range hardware without anything looking wrong in development.

We found this on our own site

We audited this site the way we audit clients', by measuring the built output rather than reading the source. Every scroll-reveal wrapper was shipping at zero opacity and every hero heading was shipping translated out of an overflow-hidden mask.

With JavaScript disabled, our homepage rendered as a blank page. On a throttled mid-tier mobile profile, homepage LCP measured 6.3 seconds — and the element the browser picked as "largest contentful" was a body paragraph, never the heading, because the heading could not count as painted while it was masked.

We are not immune to this. Nobody is, because it is invisible on a fast laptop with a warm cache.

The fix keeps the animation

You do not have to choose between motion and performance. The principle is simple: render the final state, then animate from it, rather than rendering the initial state and animating to it.

  • Let the server render content visible. Apply the hidden state only after hydration, so anything without JavaScript sees a finished page.
  • Leave content above the fold alone entirely. Animating the hero is the most expensive place to do it and the least necessary — it is already on screen.
  • Respect `prefers-reduced-motion`, which you should be doing regardless.
  • Prefer CSS transitions and scroll-driven animations where they will do the job, since they do not wait for a JavaScript bundle.

How to check your own

Open your site with JavaScript disabled. If the page is blank, your LCP is gated on hydration and your field data will be worse than your lab data.

Then measure rather than guess — our website scorecard runs Lighthouse against your live page on a mobile profile and reports Core Web Vitals alongside the on-page issues.

Motion is worth having. It is just not worth paying for it with the metric that decides whether anyone sees the page.

Do scroll animations hurt SEO?

They can, through Core Web Vitals. If content starts at zero opacity and only becomes visible once JavaScript runs, Largest Contentful Paint is measured from after your bundle downloads, parses and hydrates on the visitor's device. Google's threshold is 2.5 seconds for good and over 4 seconds for poor, and a hero that waits for hydration can cross that on mid-range hardware.

How do I keep animations without hurting performance?

Render the final state on the server and animate from it rather than to it. Apply the hidden state only after hydration, leave above-the-fold content unanimated since it is already on screen, respect prefers-reduced-motion, and prefer CSS transitions where they will do the job because they do not wait for a JavaScript bundle.

Enjoyed this? Let's work together.

Start a project