← All notes

Why your scroll animations lag on mobile

Most janky scroll animations come from the same few mistakes. Here is what to check before you blame GSAP.

31 Oct 20261 min readPerformance, GSAP

A scroll animation that feels smooth on a laptop can stutter on a mid-range phone. It is rarely the library's fault. It is usually one of a handful of habits.

Animate transform and opacity only

The browser can move and fade a layer on the GPU without redoing layout. Anything else (top, left, width, height, margin) forces it to recalculate the page on every frame.

// Layout on every frame
gsap.to(card, { top: 200 })
 
// Composited, cheap
gsap.to(card, { y: 200 })

Stop reading layout inside the loop

Calling getBoundingClientRect() or offsetWidth inside an onUpdate makes the browser flush layout every frame. Measure once, before the animation, and reuse the number.

const width = el.offsetWidth // once
 
ScrollTrigger.create({
  onUpdate: ({ progress }) => {
    gsap.set(bar, { x: progress * width })
  },
})

Be careful with filter and big blurs

filter: blur() and large box-shadow animations are expensive on phones. If you need a blur, blur a small element, or fade between a sharp and a pre-blurred copy.

Don't pin everything

Pinned sections are great for a moment of focus, but every pin adds work on resize and refresh, and long pins make the page feel endless on a phone. Pin one thing, keep it short.

Respect reduced motion

Some people get dizzy from motion. Check the preference and give them the end state:

if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
  gsap.set(el, { opacity: 1, y: 0 })
  return
}

Test on a real phone

Chrome's device mode emulates the screen size, not the CPU. Plug in a real phone, or at least throttle the CPU in DevTools, before you call it done.

Need this on your site?

I build interfaces like this for agencies, startups and SaaS teams.

Let's talk