fixing-motion-performance
Selective Reading Rule
Start with:
references/senior-master-standard.md
references/usage-routing.md
references/quality-checklist.md
Then load only the inherited docs, scripts, assets, or examples that match the user's actual task.
Fix animation performance issues.
how to use
Do not migrate animation libraries unless explicitly requested. Apply rules within the existing stack.
When to Use
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
- composite: transform, opacity
- paint: color, borders, gradients, masks, images, filters
- layout: size, position, flow, grid, flex
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)
- do not interleave layout reads and writes in the same frame
- do not animate layout continuously on large or meaningful surfaces
- do not drive animation from scrollTop, scrollY, or scroll events
- no requestAnimationFrame loops without a stop condition
- do not mix multiple animation systems that each measure or mutate layout
2. choose the mechanism (critical)
- default to transform and opacity for motion
- use JS-driven animation only when interaction requires it
- paint or layout animation is acceptable only on small, isolated surfaces
- one-shot effects are acceptable more often than continuous motion
- prefer downgrading technique over removing motion entirely
3. measurement (high)
- measure once, then animate via transform or opacity
- batch all DOM reads before writes
- do not read layout repeatedly during an animation
- prefer FLIP-style transitions for layout-like effects
- prefer approaches that batch measurement and writes
4. scroll (high)
- prefer Scroll or View Timelines for scroll-linked motion when available
- use IntersectionObserver for visibility and pausing
- do not poll scroll position for animation
- pause or stop animations when off-screen
- scroll-linked motion must not trigger continuous layout or paint on large surfaces
5. paint (medium-high)
- paint-triggering animation is allowed only on small, isolated elements
- do not animate paint-heavy properties on large containers
- do not animate CSS variables for transform, opacity, or position
- do not animate inherited CSS variables
- scope animated CSS variables locally and avoid inheritance
6. layers (medium)
- compositor motion requires layer promotion, never assume it
- use will-change temporarily and surgically
- avoid many or large promoted layers
- validate layer behavior with tooling when performance matters
7. blur and filters (medium)
- keep blur animation small (<=8px)
- use blur only for short, one-time effects
- never animate blur continuously
- never animate blur on large surfaces
- prefer opacity and translate before blur
8. view transitions (low)
- use view transitions only for navigation-level changes
- avoid view transitions for interaction-heavy UI
- avoid view transitions when interruption or cancellation is required
- treat size changes as potentially layout-triggering
9. tool boundaries (critical)
- do not migrate or rewrite animation libraries unless explicitly requested
- apply these rules within the existing animation system
- never partially migrate APIs or mix styles within the same component
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
- enforce critical rules first (never patterns, tool boundaries)
- choose the least expensive rendering work that matches the intent
- for any non-default choice, state the constraint that justifies it (surface size, duration, or interaction requirement)
- when reviewing, prefer actionable notes and concrete alternatives over theory
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
1---2name: fixing-motion-performance3description: ALWAYS use this when the request matches Fixing Motion Performance: Audit and fix animation performance issues including layout thrashing, compositor properties, scroll-linked motion, and blur effects.4---56# fixing-motion-performance78## Selective Reading Rule910Start with:1112- `references/senior-master-standard.md`13- `references/usage-routing.md`14- `references/quality-checklist.md`1516Then load only the inherited docs, scripts, assets, or examples that match the user's actual task.1718Fix animation performance issues.1920## how to use2122- `/fixing-motion-performance`23 Apply these constraints to any UI animation work in this conversation.2425- `/fixing-motion-performance <file>`26 Review the file against all rules below and report:27 - violations (quote the exact line or snippet)28 - why it matters (one short sentence)29 - a concrete fix (code-level suggestion)3031Do not migrate animation libraries unless explicitly requested. Apply rules within the existing stack.3233## When to Use34Reference these guidelines when:35- adding or changing UI animations (CSS, WAAPI, Motion, rAF, GSAP)36- refactoring janky interactions or transitions37- implementing scroll-linked motion or reveal-on-scroll38- animating layout, filters, masks, gradients, or CSS variables39- reviewing components that use will-change, transforms, or measurement4041## rendering steps glossary4243- composite: transform, opacity44- paint: color, borders, gradients, masks, images, filters45- layout: size, position, flow, grid, flex4647## rule categories by priority4849| priority | category | impact |50|----------|----------|--------|51| 1 | never patterns | critical |52| 2 | choose the mechanism | critical |53| 3 | measurement | high |54| 4 | scroll | high |55| 5 | paint | medium-high |56| 6 | layers | medium |57| 7 | blur and filters | medium |58| 8 | view transitions | low |59| 9 | tool boundaries | critical |6061## quick reference6263### 1. never patterns (critical)6465- do not interleave layout reads and writes in the same frame66- do not animate layout continuously on large or meaningful surfaces67- do not drive animation from scrollTop, scrollY, or scroll events68- no requestAnimationFrame loops without a stop condition69- do not mix multiple animation systems that each measure or mutate layout7071### 2. choose the mechanism (critical)7273- default to transform and opacity for motion74- use JS-driven animation only when interaction requires it75- paint or layout animation is acceptable only on small, isolated surfaces76- one-shot effects are acceptable more often than continuous motion77- prefer downgrading technique over removing motion entirely7879### 3. measurement (high)8081- measure once, then animate via transform or opacity82- batch all DOM reads before writes83- do not read layout repeatedly during an animation84- prefer FLIP-style transitions for layout-like effects85- prefer approaches that batch measurement and writes8687### 4. scroll (high)8889- prefer Scroll or View Timelines for scroll-linked motion when available90- use IntersectionObserver for visibility and pausing91- do not poll scroll position for animation92- pause or stop animations when off-screen93- scroll-linked motion must not trigger continuous layout or paint on large surfaces9495### 5. paint (medium-high)9697- paint-triggering animation is allowed only on small, isolated elements98- do not animate paint-heavy properties on large containers99- do not animate CSS variables for transform, opacity, or position100- do not animate inherited CSS variables101- scope animated CSS variables locally and avoid inheritance102103### 6. layers (medium)104105- compositor motion requires layer promotion, never assume it106- use will-change temporarily and surgically107- avoid many or large promoted layers108- validate layer behavior with tooling when performance matters109110### 7. blur and filters (medium)111112- keep blur animation small (<=8px)113- use blur only for short, one-time effects114- never animate blur continuously115- never animate blur on large surfaces116- prefer opacity and translate before blur117118### 8. view transitions (low)119120- use view transitions only for navigation-level changes121- avoid view transitions for interaction-heavy UI122- avoid view transitions when interruption or cancellation is required123- treat size changes as potentially layout-triggering124125### 9. tool boundaries (critical)126127- do not migrate or rewrite animation libraries unless explicitly requested128- apply these rules within the existing animation system129- never partially migrate APIs or mix styles within the same component130131## common fixes132133```css134/* layout thrashing: animate transform instead of width */135/* before */ .panel { transition: width 0.3s; }136/* after */ .panel { transition: transform 0.3s; }137138/* scroll-linked: use scroll-timeline instead of JS */139/* before */ window.addEventListener('scroll', () => el.style.opacity = scrollY / 500)140/* after */ .reveal { animation: fade-in linear; animation-timeline: view(); }141```142143```js144// measurement: batch reads before writes (FLIP)145// before — layout thrash146el.style.left = el.getBoundingClientRect().left + 10 + 'px';147// after — measure once, animate via transform148const first = el.getBoundingClientRect();149el.classList.add('moved');150const last = el.getBoundingClientRect();151el.style.transform = `translateX(${first.left - last.left}px)`;152requestAnimationFrame(() => { el.style.transition = 'transform 0.3s'; el.style.transform = ''; });153```154155## review guidance156157- enforce critical rules first (never patterns, tool boundaries)158- choose the least expensive rendering work that matches the intent159- for any non-default choice, state the constraint that justifies it (surface size, duration, or interaction requirement)160- when reviewing, prefer actionable notes and concrete alternatives over theory161162## Limitations163- Use this skill only when the task clearly matches the scope described above.164- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.165- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.