← All articles

[ Blog ]

September 11, 2026

12 min read

Category: Insights

Website Animation Laggy on iPhone? The Real Fix

Your website animation is laggy on iPhone but smooth on the laptop it was built on. Here is the real cause, the fix, and how to test it honestly.

PerformanceiOSSafariGSAPCSSMobile
Website Animation Laggy on iPhone? The Real Fix

You approved the site on a MacBook. It was beautiful — text wiped in as you scrolled, sections glided, everything felt expensive. Then you opened it on your own iPhone, and the same scroll juddered like a bad video call. If your website animation is laggy on iPhone but smooth on desktop, you are not imagining it, and it is almost never "the phone's fault."

This is the moment most founders ask their developer a version of: is this fixable, or did we buy the wrong thing? Here is the honest answer, from someone who has fixed exactly this on shipped, award-winning builds — including the measurement that proves which of the two you're looking at.

Why this matters more than a benchmark number

Two things are true about the device in your hand:

  • It is the device your audience judges you on. For most brand and marketing sites, the majority of real traffic is mobile, and a large share of that is iOS Safari. Your laptop is the minority case.
  • Jank reads as "cheap" long before anyone measures it. Nobody on your site thinks "that's 22 frames per second." They think this feels broken — and they think it about your brand, not about your JavaScript. It is the same instinct as a door that sticks in a showroom.

So the stutter is not a technical footnote to clean up after launch. It's a positioning problem. And the good news is that in my experience it's usually a narrow problem with a cheap fix, not a rebuild.

Why the laptop lied to you

Your developer's machine has an active cooling fan, wall power, a desktop-class GPU, and a browser (usually Chrome) with a different rendering engine than the one on your phone. Your iPhone has none of that, plus:

  • A different engine. Every browser on iOS — Safari, Chrome, Firefox, all of them — is required to render with WebKit. "Try Chrome on your phone" is not a test; it's the same engine wearing a different icon.
  • Thermal and power throttling. The phone quietly slows itself down when it gets warm or when Low Power Mode is on. Your laptop doesn't do that while plugged in.
  • A much smaller budget per frame. To hit 60fps, the browser has about 16 milliseconds to produce each frame. A desktop can waste 10 of those and still look fine. A phone can't.

None of this means "phones can't do animation." Sites with far heavier motion than yours run at 60fps on a mid-range phone. It means the build has to be made for that budget, and it's easy to accidentally not do that when every review happens on a 16-inch screen.

The real cause: usually not the animation, but what's underneath it

Here's the case that taught me to stop trusting the obvious suspect.

A scroll-driven text reveal — the kind where a headline wipes in from left to right as you scroll — was running below 10 frames per second on Safari, both on iOS and on a Mac. On Chrome it was fine. The effect was built with an animated CSS mask: a gradient that slides across the text as the scroll position changes.

Plain-language version: the animation looked like the problem, so everyone assumed the wipe effect was too expensive. It wasn't.

.headline {
  /* the "expensive-looking" part — the animated wipe */
  -webkit-mask-image: linear-gradient(
    100deg,
    #000 var(--i),
    transparent var(--f)
  );
  mask-image: linear-gradient(100deg, #000 var(--i), transparent var(--f));

  /* the part that actually cost the frames */
  text-shadow: 0 4px 40px rgba(0, 0, 0, 0.25);
}

Here is the mechanic that matters. An animated mask forces the browser to repaint the masked element every single frame — it can't cache the result and just slide it around on the GPU. Repainting text is cheap. Repainting text with a 40px blurred shadow behind it is not: the browser re-renders that blur, for every letter, sixty times a second.

Plain-language version: the wipe was fine. A soft shadow sitting behind the headline had to be redrawn from scratch on every frame, and that's what blew the budget.

The proof took one line. Setting opacity: 0 on the element — which removes it visually but keeps the same animation running — took the page from under 10fps to 120fps. Opacity is a "compositor-only" property: the browser paints the element once and the GPU handles the rest. If turning the element invisible fixes the frame rate, the cost is painting, not the animation logic.

Worth knowing what didn't work: switching the animation from the gradient stops to mask-position changed nothing. The gradient was never the expense.

The fix, cheapest first

I run these in order. Most of the time the first one ends it.

1. Delete decoration that isn't visible anyway

Plain-language version: check whether the expensive effect is even doing anything on screen before you optimise it.

That 25%-black shadow was sitting on a dark section. It was invisible. Deleting it produced a pixel-identical page, kept the wipe effect exactly as designed, and removed the entire repaint cost.

  .headline {
    mask-image: linear-gradient(100deg, #000 var(--i), transparent var(--f));
-   text-shadow: 0 4px 40px rgba(0, 0, 0, 0.25);
  }

This is the single highest-value five minutes in mobile performance work, and it is routinely skipped because "delete it" doesn't feel like engineering.

2. Sweep the whole site for large blurs on moving elements

Plain-language version: blur is the most expensive common effect on the web, and it's usually decorative.

Search the stylesheets for filter: blur(, backdrop-filter, and big text-shadow / box-shadow radii, and cross-reference them against anything that animates or sits inside something that animates. On the same build, a filter: blur(77px) on a large glowing box was replaced with a radial-gradient — visually near-identical, effectively free.

/* before: the GPU redraws a 77px blur every frame */
.glow { filter: blur(77px); background: #ff7a18; }

/* after: a gradient, painted once */
.glow {
  background: radial-gradient(
    circle at 50% 50%,
    rgba(255, 122, 24, 0.55),
    transparent 70%
  );
}

3. Only then, restructure the animation

Plain-language version: if it's still slow, change how the effect is built so the phone's graphics chip can do the work instead of the CPU.

Move to compositor-only properties — opacity and transform — which the browser can hand to the GPU without repainting:

gsap.fromTo(
  headline,
  { autoAlpha: 0, y: 40 },
  {
    autoAlpha: 1,
    y: 0,
    ease: 'none',
    scrollTrigger: { trigger: headline, start: 'top 80%', end: 'top 40%', scrub: true },
  }
);

Or keep the soft-edged wipe but make the mask static and move the content through it instead — a fixed mask on a wrapper, an inner element translated inside. One gotcha from doing this for real: the inner elements still need autoAlpha, or stacked siblings ghost through the mask's soft edge.

Rule I now apply on every build: never scrub an animated mask over content that is expensive to paint. On WebKit especially, that combination is a frame-rate cliff, not a gradual slope.


Is your new site smooth on the machine it was built on and rough on the phone your customers use? That's a diagnosable, usually cheap problem — not a rebuild. Tell me what's stuttering and I'll tell you which of the three tiers above it is.


"It's fine on the simulator" is not evidence

This is the most common false comfort in the conversation, so it deserves its own section — because it will probably come up in your next call.

If your developer tests in the Xcode Simulator, they are not testing your phone. The Simulator is a Mac app: it renders through your Mac's CPU and GPU, not an A-series chip. Apple says this outright in its own documentation — hardware devices should be used for performance testing, and you should never assume the Simulator reflects real-world performance or the capabilities of the graphics processors in iOS devices (Testing in Simulator versus testing on hardware devices).

Two practical consequences:

  1. "Smooth on the simulator" proves nothing. A Mac GPU can absorb the exact repaint cost that kills a phone. The bug simply doesn't reproduce.
  2. Never compare frame rates across different iOS-version simulators. I have watched "iOS 26 is slower than iOS 17" conclusions get drawn from screen recordings of two simulators. Those differences are mostly Xcode and host artifacts. The only valid simulator comparison is before vs after a change, on the same simulator.

The ground truth is a real device, and it takes about two minutes to set up:

  1. Connect the iPhone to a Mac by cable.
  2. On the iPhone: Settings → Apps → Safari → Advanced → Web Inspector, on.
  3. On the Mac: Safari → Develop → [your iPhone] → the open page.
  4. Open the Timelines tab, hit record, and scroll the janky section.

What you're reading in that recording is a single distinction. If the time is going into Layout / Paint / Composite, it's a rendering cost — the mask-and-blur class of problem described above. If it's going into Script (or WebGL), it's a JavaScript or 3D cost, which is a different repair. Anyone proposing a fix without that answer is guessing.

If only a simulator is available, these are the commands worth knowing — same caveat applies to the numbers:

xcrun simctl boot "iPhone 16 Pro"
open -a Simulator
xcrun simctl openurl booted https://your-site.com
xcrun simctl io booted screenshot ~/Desktop/frame.png

What's cheap and what's expensive on an iPhone

A rough map of the same visual outcome built two ways. This is the table I use to explain trade-offs to clients without a performance lecture.

EffectCheap version (phone-safe)Expensive version (frame-rate risk)
Fade / revealopacity, transformanimated mask-image, animated clip-path over complex content
Glowradial-gradientfilter: blur(60px+) on a large moving box
Soft textflat colour, or a shadow on static textlarge-radius text-shadow under an animated mask
Frosted panela semi-transparent colour or a pre-blurred imagebackdrop-filter: blur() on a scrolling element
Parallaxtransform: translate3d()animating top / background-position
Scroll videoa correctly encoded, keyframe-dense file (see below)a stock export scrubbed frame-by-frame
Big imageryresponsive, modern formats, correct dimensionsone desktop-size asset served to every device

Adjacent failure modes worth ruling out while you're in there: a scroll-scrubbed video that stutters is nearly always an encoding problem, not a code problem; and a GSAP scrubbed timeline that breaks on fast scroll looks like lag to a non-developer but is actually a logic bug. For 3D, the diagnosis path is different again — see three.js performance optimization.

The triage to ask your developer for

Send this as-is. It's about half a day of work and it ends the debate with data instead of opinions:

  1. Record a real-device Safari Timelines trace of the section that stutters, on an actual iPhone.
  2. Report the split: how much time in Layout/Paint/Composite vs Script.
  3. If paint-dominated: list every filter: blur, backdrop-filter, and large shadow inside or under an animating element — and mark which are actually visible against their background.
  4. Delete the invisible ones, re-record, and report the new frame rate.
  5. Only if it's still below 60fps, restructure the animation onto opacity/transform.
  6. Re-check the section's effect on Core Web Vitals for animation-heavy sites, so the fix doesn't quietly trade smoothness for a slower first load.

A competent developer will come back from step 4 with the fix. If step 2 is refused, or you get "it's fine on my machine" a second time, that's your signal.

Heavy animation and smooth animation are not opposites

The thing I most want you to take away: you did not buy "too much animation." Motion-led and fast on a mid-range phone is not a trade-off — it's a build decision made hundreds of times across a project, and it is the actual job of a creative developer.

The sites that win awards and convert aren't the ones with less motion. They're the ones where someone budgeted every frame: which effects earn their cost, which are decorative, which must be compositor-only, which must be disabled under prefers-reduced-motion. Done right, nobody ever notices the work — they just feel that the site is expensive, on whatever device they happen to be holding.

That's the standard I build to across my project work, and it's the standard your site should be held to.

FAQ

Why is my website smooth on desktop but slow on mobile Safari?

Because they're different engines on very different hardware. Desktop Chrome can absorb per-frame rendering costs (blurs, shadows, animated masks) that exceed an iPhone's 16ms frame budget entirely. The animation isn't "too much" — a specific paint cost inside it is too expensive.

Does testing in Chrome on my iPhone rule out a Safari bug?

No. Every iOS browser renders with WebKit, so Chrome for iOS is Safari underneath. To compare engines you need a real Android device or a desktop browser.

Is scroll animation stuttering on iOS Safari fixable without a rebuild?

In the overwhelming majority of cases, yes. The most common cause is a small number of expensive paint effects — large blurs and shadows under animated elements. Removing or replacing them is typically hours of work, not a project.

How do I measure animation performance on a real iPhone?

Connect the phone to a Mac, enable Web Inspector in Safari's advanced settings on the phone, then open Safari → Develop → your device → the page, and record in the Timelines tab. That recording is the ground truth. Xcode Simulator numbers are not.

Should I just disable animations on mobile?

That's the last resort, not the first. It's sometimes right for one heavy hero effect, but blanket-disabling motion on the device most of your audience uses means paying for a premium site and shipping a plain one. Fix the paint cost first. Do respect prefers-reduced-motion for users who ask for less motion — that's accessibility, not a performance patch.


Got a site that feels premium on the laptop and cheap on the phone? I'm an Awwwards jury member and creative developer who has spent 11+ years building motion-led sites that hold 60fps on real devices. Send me the URL and the section that stutters — you'll get a straight answer on what it is and what it takes to fix.

Related posts