GSAP Optimise — Performance Pass
Flow: gsap-setup → gsap-animate → gsap-optimise → gsap-test
References: See gsap-performance skill for extended API details.
Companion: For general GSAP performance guidance, invoke gsap-performance. This skill covers optimisation recipes and audit checklists only. Requires: greensock/gsap-skills
1. GPU Acceleration
// GOOD — GPU-composited
gsap.to(el, { x: 100, y: 50, rotation: 45, scale: 1.2, opacity: 0.8 })
// BAD — triggers layout/reflow
gsap.to(el, { left: 100, top: 50, width: '120%', height: 200 })
| force3D |
Behaviour |
Use when |
"auto" |
3D during tween, 2D after |
Default — usually best |
true |
Stay 3D permanently |
Elements animated repeatedly |
false |
Always 2D |
Upscaled images (avoids blur) |
2. will-change
CSS will-change: transform is fine for always-animating elements (scroll-driven, looping). For interactive/repeated animations, manage in JS:
self.add('applyEffect', (el) => {
el.style.willChange = 'transform'
gsap.to(el, { scale: 1.03, ...HOVER_IN })
})
self.add('resetEffect', (el) => {
gsap.to(el, { scale: 1, ...HOVER_OUT,
onComplete: () => { el.style.willChange = 'auto' }
})
})
3. High-Frequency Animations
See gsap-performance skill for quickTo, quickSetter, and piping API reference. Use the fastest tool that fits:
- Tweened cursor tracking →
gsap.quickTo()
- Per-frame value piping →
gsap.quickSetter()
- CSS custom properties → direct
style.setProperty()
4. Lazy Rendering
GSAP defers first-render writes to end of tick — avoids layout thrashing. Default lazy: true.
When multiple from()/fromTo() target the same property, set immediateRender: false on later ones.
5. Anti-Patterns
// BAD: bare gsap.to inside event handler — orphaned tween
el.addEventListener('mousemove', () => gsap.to(el, { x: 10 }))
// BAD: rapid fire without overwrite — tween pile-up => gsap.to(el, { x: pos, duration: 0.3 })
// BAD: layout properties — triggers reflow
gsap.to(el, { width: 200, height: 100, left: 50 })
// BAD: transformPerspective on every frame (set once with gsap.set)
// BAD: permanent will-change on interactive elements
// BAD: new timeline every call (create once, play/reverse)
// BAD: no reduced motion check
// BAD: markers left in production
6. Performance Audit Checklist
GPU & Rendering
High-Frequency
ScrollTrigger
Cleanup
Accessibility
References
- See gsap-performance skill for extended API: quickTo, quickSetter, pipe, ScrollTrigger.batch, scrub tuning, matchMedia, registerEffect, ticker/lagSmoothing, autoAlpha, force3D, lazy rendering internals, context cleanup internals
1---2name: gsap-optimise3description: Production recipes for GSAP performance optimisation. Apply after building animations (gsap-animate) to audit and improve performance. Companion to official gsap-performance skill (API reference). Triggers: GSAP performance, animation optimise, animation slow, jank, 60fps, memory leak, tween cleanup, force3D, will-change, quickTo, quickSetter, overwrite, layout thrashing, GPU compositing, animation audit, gsap optimise, animation performance review. Non-triggers: Not for building new animations (use gsap-animate and sub-skills). Not for testing (use gsap-test). Apply this skill AFTER animations are built. Outcome: Audits and improves existing GSAP animations for 60fps — GPU acceleration, high-frequency tools, anti-patterns, and a component-level performance checklist.4---56# GSAP Optimise — Performance Pass78> **Flow**: gsap-setup → gsap-animate → **gsap-optimise** → gsap-test9> **References**: See **gsap-performance** skill for extended API details.1011> **Companion**: For general GSAP performance guidance, invoke **gsap-performance**. This skill covers optimisation recipes and audit checklists only. Requires: `greensock/gsap-skills`1213---1415## 1. GPU Acceleration1617```js18// GOOD — GPU-composited19gsap.to(el, { x: 100, y: 50, rotation: 45, scale: 1.2, opacity: 0.8 })20// BAD — triggers layout/reflow21gsap.to(el, { left: 100, top: 50, width: '120%', height: 200 })22```2324| force3D | Behaviour | Use when |25|---------|-----------|----------|26| `"auto"` | 3D during tween, 2D after | Default — usually best |27| `true` | Stay 3D permanently | Elements animated repeatedly |28| `false` | Always 2D | Upscaled images (avoids blur) |2930---3132## 2. will-change3334CSS `will-change: transform` is fine for always-animating elements (scroll-driven, looping). For interactive/repeated animations, manage in JS:3536```js37self.add('applyEffect', (el) => {38 el.style.willChange = 'transform'39 gsap.to(el, { scale: 1.03, ...HOVER_IN })40})41self.add('resetEffect', (el) => {42 gsap.to(el, { scale: 1, ...HOVER_OUT,43 onComplete: () => { el.style.willChange = 'auto' }44 })45})46```4748---4950## 3. High-Frequency Animations5152See **gsap-performance** skill for quickTo, quickSetter, and piping API reference. Use the fastest tool that fits:53- Tweened cursor tracking → `gsap.quickTo()`54- Per-frame value piping → `gsap.quickSetter()`55- CSS custom properties → direct `style.setProperty()`5657---5859## 4. Lazy Rendering6061GSAP defers first-render writes to end of tick — avoids layout thrashing. Default `lazy: true`.6263When multiple `from()`/`fromTo()` target the same property, set `immediateRender: false` on later ones.6465---6667## 5. Anti-Patterns6869```js70// BAD: bare gsap.to inside event handler — orphaned tween71el.addEventListener('mousemove', () => gsap.to(el, { x: 10 }))7273// BAD: rapid fire without overwrite — tween pile-up74onMouseMove = () => gsap.to(el, { x: pos, duration: 0.3 })7576// BAD: layout properties — triggers reflow77gsap.to(el, { width: 200, height: 100, left: 50 })7879// BAD: transformPerspective on every frame (set once with gsap.set)80// BAD: permanent will-change on interactive elements81// BAD: new timeline every call (create once, play/reverse)82// BAD: no reduced motion check83// BAD: markers left in production84```8586---8788## 6. Performance Audit Checklist8990**GPU & Rendering**91- [ ] Only transform/opacity animated (no left/top/width/height)92- [ ] `force3D: true` on repeatedly animated elements93- [ ] `will-change` managed: CSS for scroll-driven, JS for interactive94- [ ] `autoAlpha` used instead of `opacity`9596**High-Frequency**97- [ ] `overwrite: 'auto'` on all rapid-fire tweens98- [ ] `quickTo()` for repeated animated updates99- [ ] `quickSetter()` for per-frame value piping100101**ScrollTrigger**102- [ ] `ScrollTrigger.batch()` for large grids (50+ elements)103- [ ] `once: true` on one-shot triggers104- [ ] `invalidateOnRefresh: true` on responsive layouts105- [ ] `ScrollTrigger.refresh()` after dynamic content106107**Cleanup**108- [ ] All tweens inside `gsap.context()` or `ctx.add()`109- [ ] `ctx.revert()` in `onUnmounted`110- [ ] Timelines created once and played/reversed111112**Accessibility**113- [ ] `prefers-reduced-motion` respected via `gsap.matchMedia()`114- [ ] Content visible without JavaScript115116---117118## References119120- See **gsap-performance** skill for extended API: quickTo, quickSetter, pipe, ScrollTrigger.batch, scrub tuning, matchMedia, registerEffect, ticker/lagSmoothing, autoAlpha, force3D, lazy rendering internals, context cleanup internals