All posts
Web design & development

Scroll Animations Without Killing Performance

Scroll animation performance in practice: animate transform and opacity, use CSS animation-timeline first, add GSAP ScrollTrigger only when needed.

By Mehdi Hassan7 min read

The short answer

Good scroll animation performance comes from three rules: animate only transform and opacity, use CSS scroll-driven animations with animation-timeline before reaching for JavaScript, and keep scroll work off the main thread so taps and clicks stay responsive. Add a library like GSAP ScrollTrigger only for complex choreography, and always test on a mid-range phone.

Key takeaways

  • Animate transform and opacity only. Layout properties force work on every scroll frame.
  • CSS animation-timeline runs scroll-linked effects without a scroll listener. Try it first.
  • Use IntersectionObserver for reveal-once effects instead of measuring scroll position.
  • Scroll handlers compete with taps for the main thread, which is how scroll effects hurt INP.
  • Test on a mid-range Android phone with reduced motion on and off before you ship.

Part of Motion Design for Marketing Websites: When Animation Helps and When It Hurts

Scroll animation is the most common reason a beautiful marketing site feels slow. It looks fine on the designer's laptop and stutters on a buyer's phone. The fix is rarely to remove motion. It's to build it in the right order, with the cheapest technique that does the job. This guide is part of our broader website animation rulebook.

Why do scroll animations hurt performance?

Scroll animations hurt performance when they make the browser redo layout or run JavaScript on every scroll frame. Scrolling already asks the browser to produce a new frame many times a second. If each frame also recalculates positions, repaints shadows or runs a heavy scroll handler, the browser misses frames and the page judders.

The second cost is responsiveness. JavaScript scroll work runs on the main thread, the same thread that handles taps, clicks and typing. When the main thread is busy, interactions wait, and that delay shows up in Interaction to Next Paint (INP). Field data for Q2 2026 from corewebvitals.io shows only about two-thirds of Next.js sites pass INP, with a median around 236ms, so there's little headroom for scroll effects to waste.

Technique

Main-thread cost

When to use

CSS transition on class toggle

Very low

Simple reveal once an element enters view

CSS scroll-driven animation (animation-timeline)

Very low

Progress-linked effects like parallax or progress bars

IntersectionObserver plus CSS

Low

Reveal-once effects across browsers

GSAP ScrollTrigger or Motion scroll

Medium

Pinned sections and multi-step choreography

Raw scroll event listener

High

Almost never on a marketing site

How do you add scroll animations without hurting performance?

Build scroll animation in a fixed order: decide the job, pick the cheapest technique, animate only compositor-friendly properties, then measure. Most performance problems come from skipping straight to a library and animating whatever looks good. This sequence keeps the effect and drops the cost.

  1. Name the job of the animation

    Reveal content, show progress, or explain steps. If it does none of these, cut it before optimizing it.

  2. Start with CSS animation-timeline

    For progress-linked effects, use a scroll() or view() timeline in CSS so the browser drives the animation without a scroll listener. Provide a static fallback where it isn't supported.

  3. Use IntersectionObserver for reveals

    For effects that play once when a section enters view, observe the element, add a class, and let a CSS transition do the motion. Disconnect the observer after it fires.

  4. Animate only transform and opacity

    Move with translate, grow with scale, fade with opacity. Avoid animating top, left, width, height, margin, filter blur and box-shadow.

  5. Reach for a library only for choreography

    Use GSAP ScrollTrigger or Motion for pinned sections, scrubbed timelines and multi-element sequences. Load it only on the pages that need it.

  6. Respect reduced motion

    Wrap scroll effects in a prefers-reduced-motion check and show the end state immediately when motion is reduced.

  7. Measure on a real phone

    Record a performance trace while scrolling on a mid-range Android device and check field INP in Search Console after launch.

How do CSS scroll-driven animations work?

CSS scroll-driven animations link a normal CSS animation to scroll position instead of time, using the animation-timeline property. A scroll() timeline tracks how far a container has scrolled, and a view() timeline tracks an element's progress through the viewport. You write keyframes as usual, and the browser maps scroll progress onto them.

The advantage is that no JavaScript listens to scroll at all. The browser knows the relationship ahead of time and can run compositor-friendly animations off the main thread. That makes reading progress bars, subtle parallax and section reveals nearly free. MDN's reference on animation-timeline lists current syntax and support.

Support has improved but isn't universal across every browser version your visitors use, so treat it as progressive enhancement. Wrap it in an @supports check and make sure the page looks finished without it. Visitors on older browsers simply see the static design, which is a perfectly good outcome.

For example, suppose you want a section that fades and rises as it enters view

For example, suppose a features section should rise slightly and fade in as it enters the viewport. With CSS scroll-driven animation, you define keyframes from opacity 0.4 and a small translateY to opacity 1 and no translate, set animation-timeline to view() on the section, and limit animation-range so it finishes once the section is partly on screen.

Inside an @supports (animation-timeline: view()) block, that's the whole implementation. Without support, the section simply appears in place. Inside a prefers-reduced-motion: reduce query, you remove the animation entirely. No scroll listener, no library, no layout work per frame.

Is GSAP ScrollTrigger bad for performance?

GSAP ScrollTrigger isn't bad for performance when it animates transform and opacity and is loaded only where needed. It's a mature library that batches its work carefully. The problems come from how it's used: dozens of triggers on one page, pinned sections that animate layout properties, or the library shipping on every page when one section uses it.

  • Scope it. Import the library in the component that uses it, so other pages don't pay for it.
  • Limit triggers. Group related elements into one timeline instead of one trigger per element.
  • Be careful with pinning. Pinned sections are powerful for storytelling, but they change scroll length and can confuse people on mobile. Test them with touch scrolling.
  • Clean up. In React and Next.js, kill triggers when components unmount, or route changes will leave orphaned listeners.

When GSAP, Motion or plain CSS is the right call depends on the effect, the framework and who maintains it. We give a verdict by use case in GSAP vs Motion vs CSS.

Does smooth scrolling make scroll animation performance worse?

Smooth scrolling libraries can make scroll animation feel more consistent, but they add JavaScript to every scroll and change how scroll feels for everyone. Libraries like Lenis interpolate scroll position, which pairs well with scrubbed animations because motion follows a predictable curve. The trade-off is that native scroll physics are replaced, and anything heavy on the main thread now affects scrolling itself.

If you use one, keep the rest of the page light and respect reduced-motion settings by disabling the smoothing for people who ask for less motion. Our Lenis smooth scroll guide covers when it's worth it and when to skip it.

What else slows down scroll-heavy pages?

Heavy images, web fonts and third-party scripts slow scroll-heavy pages as much as the animations do. Animation is the visible symptom, but the main thread is shared. A tag manager loading a chat widget, a heatmap tool and two pixels will make even well-built scroll effects stutter.

  • Images: serve modern formats at the right size, and lazy-load everything below the first screen. In Next.js, the patterns in next/image, fonts and scripts cover most of it.
  • Fonts: late-loading fonts shift text mid-scroll. See web font performance.
  • Third-party scripts: audit and defer them using our third-party script audit.
  • Video and Lottie: pause offscreen media, and don't autoplay several at once.

Scroll animations also distort analytics that depend on scroll. If sections only reveal on scroll, scroll depth data tells you where people stopped watching motion, not necessarily where they stopped reading.

Frequently asked questions

Do scroll animations affect Core Web Vitals?
They can affect all three. Content hidden until scroll can delay LCP if it's the largest element, animations that change layout can cause layout shift, and JavaScript scroll handlers can block the main thread and worsen INP. Animating only transform and opacity, keeping key content visible and avoiding scroll listeners prevents most of the impact.
Should I use will-change on scroll animations?
Use will-change sparingly, only on elements that are about to animate, and remove it when the animation finishes. It hints the browser to promote the element to its own layer, which can smooth motion. Applied to many elements at once, it costs memory and can make performance worse, especially on phones with limited graphics memory.
Are parallax effects bad for performance?
Parallax is fine for performance when it's built with transform and a CSS scroll timeline or a well-scoped library. It becomes expensive when it changes background-position or top on every scroll event. Parallax also causes discomfort for people with vestibular disorders, so disable it entirely under prefers-reduced-motion rather than just reducing it.
How do I test scroll animation performance?
Record a performance trace in Chrome DevTools while scrolling, with CPU throttling on, and look for long tasks and dropped frames. Then test on a real mid-range Android phone, because desktop machines hide most problems. After launch, check field INP in Search Console or your real-user monitoring, since lab tests don't capture every device.
Can Framer or Webflow scroll effects be fast?
Yes, when they're used with restraint. Both platforms' built-in scroll effects generally animate transform and opacity. Problems usually come from stacking many effects on one page, large unoptimized media, or custom code added on top. Keep effects to the sections that need them and check the published page on a phone.

· CEO & Design Director

Copywriter, designer and developer, and founder of Designify Studio. Over five years, 60+ projects across 14+ industries, for startups that have raised $300M+.

Want this done for you? Website, $8,000.

A multi-page marketing site, written and designed by us, developed in Next.js and animated. $8,000, one-time, up to 6 pages. Book a free 30-minute call to see if it fits.

Schedule Call