UIMotion

Fixing Motion Performance

Audit and fix animation performance issues including layout thrashing, compositor properties, scroll-linked motion, and blur effects.

JJulien Thibeaut (ibelick)·UI·MIT

Library skill — the default version is maintained in GitHub; edits you make live in your own clone.

Use this skillDownload .zip
How does this work?
  • ChatGPT opens a new chat with the skill loaded. If it's too long for a link, it's copied to your clipboard — just paste.
  • Claude works the same way. To install it permanently, download the .zip and upload it under Claude → Settings → Capabilities → Skills (Pro/Team/Enterprise).
  • Copy prompt copies the skill so you can paste it into any assistant, including Grok.

fixing-motion-performance

Fix animation performance issues.

how to use

Do not migrate animation libraries unless explicitly requested. Apply rules within the existing stack.

when to apply

Reference these guidelines when: - adding or changing UI animations (CSS, WAAPI, Motion, rAF, GSAP) - refactoring janky interactions or transitions - implementing scroll-linked motion or reveal-on-scroll - animating layout, filters, masks, gradients, or CSS variables - reviewing components that use will-change, transforms, or measurement

rendering steps glossary

rule categories by priority

priority category impact
1 never patterns critical
2 choose the mechanism critical
3 measurement high
4 scroll high
5 paint medium-high
6 layers medium
7 blur and filters medium
8 view transitions low
9 tool boundaries critical

quick reference

1. never patterns (critical)

2. choose the mechanism (critical)

3. measurement (high)

4. scroll (high)

5. paint (medium-high)

6. layers (medium)

7. blur and filters (medium)

8. view transitions (low)

9. tool boundaries (critical)

common fixes

/* layout thrashing: animate transform instead of width */
/* before */ .panel { transition: width 0.3s; }
/* after */  .panel { transition: transform 0.3s; }

/* scroll-linked: use scroll-timeline instead of JS */
/* before */ window.addEventListener('scroll', () => el.style.opacity = scrollY / 500)
/* after */  .reveal { animation: fade-in linear; animation-timeline: view(); }
// measurement: batch reads before writes (FLIP)
// before — layout thrash
el.style.left = el.getBoundingClientRect().left + 10 + 'px';
// after — measure once, animate via transform
const first = el.getBoundingClientRect();
el.classList.add('moved');
const last = el.getBoundingClientRect();
el.style.transform = `translateX(${first.left - last.left}px)`;
requestAnimationFrame(() => { el.style.transition = 'transform 0.3s'; el.style.transform = ''; });

review guidance