You Added will-change to Fix the Jank. You Made It Worse.
will-change: transform looks like a free performance switch. Applied broadly or left on permanently, it does the opposite — here's the narrow, temporary pattern that actually works.

Open DevTools on almost any site that's been "optimized" for animation and check the Layers panel. There's a decent chance half the card grid, the nav, a modal backdrop, and a few divs nobody can explain are each sitting in their own compositor layer — because at some point, someone added will-change: transform to fix a stutter, and it never came back off.
The property does exactly what it promises, which is the whole problem. Set it on one element, right before that element animates, and the browser can promote it to the GPU ahead of time instead of scrambling mid-animation. The jank goes away. That's a real, measurable win — and it's also the exact experience that teaches people the wrong lesson: will-change makes animations smooth, so sprinkle it wherever something moves.
That's the myth. It falls apart the moment it meets a loop.
Here's the version that ships after someone reads "just add will-change":
If your page has one .card, this is fine — arguably exactly right. If .card is a grid of 200 dashboard tiles, this rule now applies to all 200 of them, permanently, the moment the stylesheet loads. Not "while hovering." Not "while animating." Forever, whether that card has moved once or never.
Each one of those 200 elements is a standing request to the browser: keep a compositor layer ready for this, indefinitely, just in case. MDN is direct about what that costs: "overusing the property can cause the page to slow down instead of improving its performance," and the fix is to use it "sparingly," on "deeply nested elements, containing as little of the document as possible" — the opposite of a blanket rule on a repeated class. The CSS spec puts the extreme case more bluntly: push it far enough and it "can cause the page to slow down or even crash."
There's also a version of this mistake the browser won't even let you make: will-change: all looks tempting as a catch-all, but it's explicitly disallowed in the spec, specifically so people can't do what the .card rule above does by accident with a long, honest property list instead.
Nobody adds will-change to be reckless. They add it to one laggy modal, watch the animation go from choppy to smooth in DevTools, and reasonably conclude: more of this, applied more broadly, should help more. The demo that teaches the property is always a single element. The failure only shows up at scale, after the feature ships, on a machine with less GPU memory than whoever wrote the CSS was testing on — which is exactly the kind of bug report that never says "it's the will-change rule" in the subject line.
will-change isn't a performance mode you flip on. It's a promise to the browser, and like any promise, breaking it has a cost. "This specific element's transform is about to change" is a promise you can keep for one element for a few hundred milliseconds. "Every card in this grid might change at some unknown point" is a promise you can't keep, and the browser ends up paying for the ones you broke.
The pattern that holds up adds the hint in JavaScript, right before the change, and removes it right after:
Now the browser only reserves a layer for the exact window where it's useful — from the moment you signal intent to the moment the transition actually finishes — and gives that memory back immediately after. One card hovered is one layer, briefly. Two hundred cards sitting untouched are two hundred cards costing nothing.
Runs right in your browser — poke at it and watch the concept react live.
Most elements on most pages don't need this property, full stop. Browsers already run their own heuristics for promoting layers around transform and opacity changes, and for a single button or a handful of elements, those heuristics are usually good enough on their own. will-change is specifically for the case you've already profiled: you opened the Performance or Layers panel, watched a specific element genuinely struggle, and confirmed a manual hint fixes it. MDN's own framing is "use it as a last resort to deal with existing performance problems" — never "add it in advance in case one shows up." If you haven't profiled anything yet, you don't have evidence will-change is the fix; you have a hunch, and hunches are how a stylesheet ends up with a permanent rule on .card.
will-change doesn't make anything faster in the way a code change makes a function faster — it changes when the browser pays a cost it was always going to pay, trading a little memory for a smoother first frame. On a memory-constrained device, that trade can go the other way: enough simultaneous layers and you're not avoiding jank, you're causing it, just somewhere else in the pipeline. The fix for "I added will-change and it's still janky" is often "remove will-change and check whether you're promoting too much at once" — not "add more of it."
will-change works exactly as advertised on exactly as much as you apply it to. The mistake was never the property — it was treating a scoped, temporary hint like a global setting you set once and forget. Scope it to the element that's actually changing, add it right before the change, take it back off right after, and you get the smooth animation without two hundred standing GPU layers paying for cards that never moved.
Go check your own stylesheet for a bare will-change sitting on a class that matches more than one element — how many of those elements have actually animated today?
Think it clicked? Take the 8-question quiz →
Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.
- Your browser renders everything, even what you can't see —
content-visibility: autofixes that - You're polling setInterval to detect DOM changes.
MutationObserverfires when they happen. - The Background Task That Waited 40 Seconds for 'Idle'
🚀 Want more like this? Every guide, playground, and quiz lives on bestpractic.org — open it and sign up free so the next one finds you.
Thanks for reading! Let's stay connected:
- ⭐ GitHub — follow me and star the projects: github.com/parsajiravand
- 💬 Discord — join the frontend best-practices community: discord.gg/d9KRhuAwQ
- 📸 Instagram — frontend best practices, daily: @bestpractice___
Keep reading
One post a day, in your inbox
Each one with a runnable playground and a quiz. No pitch, no digest, unsubscribe in one click.
0 comments
Sign in to join the discussion, like comments, and save articles for later.