HomeServicesAboutBlogContact Türkçe

We Added Scroll Animation to Our Site, and Speed Didn't Move

We added scroll-reveal animations and a scroll-reactive header effect to our own site. Result: no new library, no extra network request, and no measurable hit to Core Web Vitals. Here's how we did it.

In short: The scroll-reveal animations we added to our site don't require a new library or an extra network request. We use transform and opacity — properties the browser runs on the GPU without triggering layout — along with IntersectionObserver, so Core Web Vitals (LCP, CLS, INP) stay unaffected.

Why Adding Animation Usually Slows Things Down

When a site needs "boxes that fade in on scroll," the first instinct is often a React-based animation library. Those libraries aren't bad on their own, but they mean shipping extra JavaScript the browser has to download and run. The page becomes interactive later, and sometimes the animated elements cause a layout shift while they load.

What we needed didn't call for that much machinery — a few elements fading in on scroll, and a header that reacts slightly to scrolling.

What We Actually Added

  • No new library or dependency — file count and HTTP requests stayed the same
  • About 20 lines of CSS in global.css
  • About 20 lines of inline script in Layout.astro — not a separate file, no extra network request
  • The header's scroll detection is registered with { passive: true }, so it never blocks scrolling

Why Transform and Opacity

The animations only change opacity and transform. Both properties can be handled by the browser on the GPU, on the compositor thread, without recalculating the page's layout. In practice, that means the page doesn't shift while the animation runs — CLS stays clean.

IntersectionObserver, Not a Scroll Event

The old way to detect whether an element is visible was to attach a function to the scroll event and recalculate the element's position on every scroll tick — running dozens of times a second and keeping the main thread busy.

IntersectionObserver instead tells the browser "let me know when this element becomes visible," and the browser handles that calculation without tying up the main thread. It's the approach modern browsers recommend.

The One "Not Quite Zero" Detail

The background glow in the hero section loops continuously for as long as the page is open. That's not entirely free, but it still relies on transform/opacity, so the browser handles it cheaply — and browsers already throttle that kind of animation on their own once a tab is backgrounded or the element is off-screen.

What This Means for Our Clients

We used this approach on our own site, but it's the same principle behind our web design service for clients: visual motion shouldn't come at the cost of Core Web Vitals — it comes from picking the right API for the job. We hold the same standard for work we deliver through our agency partnerships abroad.

Frequently Asked Questions

Does adding scroll animation hurt SEO?

Not if it's done right. Google uses Core Web Vitals (LCP, CLS, INP) as a ranking signal, and animation only becomes a problem when it pushes those metrics in the wrong direction. The issue is rarely the animation itself — it's usually the heavy library brought in to produce it.

Why didn't you use a library like React or Framer Motion?

For an effect as simple as 'fade in on scroll,' pulling in a library means shipping and running extra JavaScript the browser has to download and execute. A few lines of CSS and a native browser API already covered what we needed.

What is IntersectionObserver, and why use it instead of a scroll event?

IntersectionObserver asks the browser to tell you when an element becomes visible. A scroll event listener recalculates on every pixel scrolled; IntersectionObserver only fires when it actually needs to, which makes it far cheaper.

Does the looping background animation in the hero affect performance?

Not measurably — it also relies on transform/opacity, and browsers already throttle that kind of animation automatically once a tab is backgrounded or the element scrolls out of view.