HomeMethod

Knowledge

Web VitalsTechniquesSnippetsAnswersImpactsBottlenecks

Use Composited Animations

Animate only transform and opacity so animations run on the GPU and never block the main thread.

Overview

The browser compositing pipeline separates work between the main thread (layout, paint) and the compositor thread (GPU compositing). Animations that change transform or opacity run entirely on the compositor thread — they never block JavaScript or input handling, and never trigger layout or repaint. Animating any other CSS property (width, height, top, left, margin, padding) forces the browser back to the main thread on every frame, consuming 6–16 ms per frame that should be going to user interactions.

Impact grade, A+ to D: how much of the Lighthouse score this technique can move. Unaffected: LCP, FCP, SI, TTFB.

The Problem

A CSS animation that changes width from 0 to 100% runs 60 layout-and-paint cycles per second. Each cycle takes 6–16 ms on the main thread — the same thread handling JavaScript, user input, and INP measurement. On a page with 3 simultaneously animating elements using layout properties, 30–50% of the main thread’s frame budget is consumed by animation, leaving insufficient time for event handlers to respond within the 200 ms INP threshold.

Performance Impact

TBT

50–200ms

main thread freed from per-frame layout and paint during load animations

CLS

0.05–0.25

transform does not affect document flow; layout-shifting animations eliminated

Risk: Low

transform and opacity achieve the same visual effects — requires CSS refactoring

How it works

  1. 01

    Replace position/size animations with transform

    Instead of animating left/top, use transform: translate(x, y). Instead of animating width/height, use transform: scale(sx, sy). transform does not affect document flow — other elements do not reflow around it.

  2. 02

    Replace visibility animations with opacity

    Instead of toggling display: none/block or animating visibility, animate opacity from 0 to 1. Combine with pointer-events: none when fully transparent to prevent invisible elements from capturing clicks.

  3. 03

    Use will-change to promote elements ahead of time

    Add will-change: transform to elements about to animate to hint the browser to create a GPU compositing layer in advance. Do not apply it to more than 4–5 elements at once — each layer consumes GPU memory.

  4. 04

    Audit with DevTools Rendering panel

    Open Chrome DevTools → More tools → Rendering. Enable ‘Paint flashing’ — green overlays appear on regions being repainted. Non-composited animations show constant green flashing. ‘Layer borders’ shows which elements are on their own compositor layer (outlined in orange).

Limitations

  • transform: scale() changes the visual size without changing layout dimensions — surrounding content does not reflow, which is the desired behaviour but may require adjusting surrounding spacing.
  • will-change should be applied dynamically (added on hover/focus start, removed on end) for elements that only occasionally animate, to avoid permanent GPU memory usage.
  • Some design effects (animating box-shadow, border-radius at large scale) are difficult to achieve without non-composited properties — use filter: drop-shadow as a composited alternative to box-shadow where possible.

Common Mistakes

Adding will-change to every animated element as a blanket optimisation

will-change creates a GPU compositing layer immediately and holds it permanently. Too many layers exhausts GPU memory and can make the page slower. Add will-change only to elements with complex, frequently-triggered animations.

Animating margin or padding to create spacing effects

margin and padding affect document flow — every frame reflows all adjacent elements. Use transform: translate() for motion effects and keep spacing properties static.

Test this techniqueCLS DiagnosticsRun the tool

Need help applying this to your site?

Targeted fixes, not guesswork. We identify which techniques move the needle for your specific WordPress stack.

Start an Engagement
Support our family now