Performance

will-change

will-change is a CSS property that hints to the browser which properties are about to animate, letting it pre-promote the element to its own GPU layer. Used right, it eliminates the first-frame jank that happens when the browser scrambles to compositing on tween start. Used wrong (everywhere, always), it blows memory and slows the whole page.

Updated June 2, 2026

Mechanics

How will-change works

When the browser sees will-change: transform, it promotes the element to its own compositor layer immediately - before any animation runs. Layer promotion is what makes GPU-accelerated transforms cheap, but it also costs memory. By hinting in advance, you skip the cost of promoting on the first animation frame.

styles.css

Set will-change on the CSS class for elements that animate often - buttons with hover states, scroll-pinned layers, decorative loops. Skip it for elements that only animate once on page load - GSAP's force3D handles those during the tween and cleans up after.

Cleanup

Clear will-change when done

Permanent will-change on every element is a memory bomb. Browsers warn about it; mobile devices crash. For one-shot animations, set will-change just-in-time and clear it after:

script.js
When

Use will-change for

  • Elements with frequent hover-driven transforms (buttons, magnetic effects)
  • Scroll-pinned layers that animate continuously (parallax backdrops)
  • Decorative loops (rainbow gradients, breathing pulses) where the element never sits idle
  • Sticky headers that hide/show on scroll - the transition is short and frequent
  • Anywhere first-frame jank is visible in DevTools' Performance panel
Alternatives

Use something else when

  • One-shot animations on page load - GSAP's force3D: 'auto' handles promotion during the tween and cleans up after
  • Long lists of mostly-static items (grid tiles, gallery thumbnails) - 100 will-change'd elements crashes mobile; set will-change only on the few currently animating
  • Animations that change which property is animated dynamically - will-change can't adapt; clear it and let GSAP's force3D handle the active tween
  • When the page already feels smooth - don't pre-optimize
In production

Used in these Annnimate components

  • The Parallax scene sets will-change: transform on every parallax layer's CSS class so each composites on its own layer for the scrub duration
  • The Magnetic Button sets will-change: transform on the button so the hover-driven pointer tracking never jitters on first move
  • The Rainbow Button uses will-change: background-position because the continuous gradient drift benefits from layer promotion
  • The Hide Header sets will-change: transform on the header so the hide/show toggle is instant on first scroll past the threshold
Used in components

See it running in production

FAQ

Common questions

What's the difference between will-change and force3D?
will-change is a CSS hint that lives on the class - the browser promotes immediately and keeps the layer as long as the rule applies. force3D is a JS-level GSAP option that adds a 3D matrix during the tween and removes it on complete. CSS will-change for elements that animate often; GSAP force3D for one-shot animations.
Why does will-change make my page slower?
Too many layers. Every will-change'd element costs GPU memory and adds compositing work. A grid with 100 will-change tiles is slower than a grid with none. Use will-change selectively - on the few elements that actually need it, not as a blanket optimization.
Can I set will-change on hover only?
Yes, and it's a common pattern: :hover { will-change: transform; }. The browser pre-promotes when the user starts to interact, then drops the layer when they leave. Cleaner than always-on will-change. Note: some browsers throttle promotion on hover, so test.
Why does will-change blur my text?
GPU layers use sub-pixel interpolation, which softens text. If the will-change'd element contains rendered text and isn't animating, the blur is visible. Fix: limit will-change to elements that don't contain text, or accept the blur during the animation and remove will-change once it ends.
Should I prefer will-change in CSS or set it via gsap.set()?
CSS for elements that animate often - the rule is the source of truth, no JS dependency. gsap.set() for just-in-time promotion + cleanup on complete. The two compose: declare CSS will-change for steady-state elements, use gsap.set for one-shot promotion-then-cleanup cycles.