⚡ 60fps · GPU Compositing

Animation Performance Checker

Lighthouse says “avoid non-composited animations” but never tells you which ones or how to fix them. This tool parses every @keyframes on your page, flags the CPU-heavy ones and gives an exact transform/opacity conversion for each.

How does the Animation Performance Checker work?

It fetches your page’s HTML and CSS in your browser — inline styles plus up to 6 external stylesheets, including cross-origin CDNs — parses every @keyframes block, and classifies each animated property: transform and opacity are GPU-composited (cheap), paint properties like color and filter repaint every frame (moderate), and layout properties like left, width or background-position reflow the page every frame (expensive). It also catches duplicate @keyframes names — a sneaky bug where the last definition silently wins. It reads prefixed @-webkit-keyframes and first-level @import files too, and if a stylesheet resists fetching you can paste the .css file URL directly as the input.

  1. Enter a URL — ideally the page Lighthouse flagged.
  2. Check the GPU-friendly score — the share of animations that are composited.
  3. Open each flagged keyframe — it lists the offending properties and which rules use it.
  4. Apply the suggested conversion — same visual effect, transform/opacity only.
  5. Gate ambient loops on mobile and add a prefers-reduced-motion block.

Which CSS properties are safe to animate?

Only transform and opacity are fully GPU-composited — they skip layout and paint entirely and stay smooth at 60fps even on cheap phones. Everything else costs main-thread time every single frame: paint properties repaint the element, and layout properties reflow the whole page. The table below shows the standard conversions.

Instead of animating…Use this composited equivalent
left / top / right / bottomtransform: translateX() / translateY()
width / heighttransform: scaleX() / scaleY()
background-position (gradient flow)Make the element ~300% wide with a seamless gradient, animate translateX(-66.667%)
box-shadow pulsetransform: scale() pulse, or shadow on a ::after with opacity
border-color / SVG fillStatic colour on the class + opacity in the keyframes

Frequently asked questions

An animation that changes properties the GPU can’t handle alone — anything except transform and opacity. The browser must recalculate layout or repaint on the CPU for every frame, which causes jank, battery drain and a failed Lighthouse audit.
It counts every element running a non-composited animation — one bad @keyframes used by many elements multiplies fast. Fix the keyframes definition once and every element using it becomes composited.
If two @keyframes blocks share a name, CSS silently uses only the LAST one for the entire document — the earlier animation never runs. It usually happens when styles are appended over many versions. This tool lists every duplicated name.
No — each suggestion reproduces the same visual effect with composited properties: a shine that animated left becomes a translateX sweep, a flowing gradient becomes a wide strip translating, a border pulse becomes an opacity fade. Same look, no main-thread cost.
Keep entrance and interaction animations, but pause ambient infinite loops (auroras, floating blobs, twinkles) under @media(max-width:768px) — phones gain battery and smoothness with no real visual loss. Always ship a prefers-reduced-motion block too.
No — it audits CSS @keyframes from the page’s HTML and up to 6 external stylesheets, including cross-origin CDNs. JS-driven animations (GSAP, Web Animations API) and cross-origin CSS aren’t covered; Chrome DevTools’ Performance panel handles those.

More creator tools