gsap-setup
Installation
SKILL.md
GSAP Setup and Best Practices
Proper GSAP setup ensures smooth development, optimal performance, and maintainable code. Learn installation, plugin registration, configuration, and industry best practices.
Installation
NPM Installation
# Core GSAP
npm install gsap
# React integration
npm install @gsap/react
# All plugins are included in gsap package
# No separate installation needed
CDN Installation
<!-- GSAP Core -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
<!-- ScrollTrigger -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/ScrollTrigger.min.js"></script>
<!-- Other plugins as needed -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Draggable.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Flip.min.js"></script>
ES Modules (CDN)
<script type="module">
import gsap from 'https://cdn.jsdelivr.net/npm/gsap@3.13.0/index.js'
import { ScrollTrigger } from 'https://cdn.jsdelivr.net/npm/gsap@3.13.0/ScrollTrigger.js'
gsap.registerPlugin(ScrollTrigger)
</script>
Project Setup
Basic Setup
// gsap.js - Central GSAP configuration
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { Draggable } from 'gsap/Draggable'
// Register all plugins once
gsap.registerPlugin(ScrollTrigger, Draggable)
// Set global defaults
gsap.defaults({
ease: 'power2.out',
duration: 1
})
// Configure ScrollTrigger
ScrollTrigger.config({
ignoreMobileResize: true,
autoRefreshEvents: 'visibilitychange,DOMContentLoaded,load'
})
export { gsap }
Advanced Setup
// gsap.js
import gsap from 'gsap'
// Plugins (all shipped in the public `gsap` npm package; some were formerly members-only)
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { Observer } from 'gsap/Observer'
import { Draggable } from 'gsap/Draggable'
import { Flip } from 'gsap/Flip'
import { ScrollToPlugin } from 'gsap/ScrollToPlugin'
// Formerly members-only / bonus plugins
import { SplitText } from 'gsap/SplitText'
import { MorphSVGPlugin } from 'gsap/MorphSVGPlugin'
import { MotionPathPlugin } from 'gsap/MotionPathPlugin'
import { DrawSVGPlugin } from 'gsap/DrawSVGPlugin'
import { ScrambleTextPlugin } from 'gsap/ScrambleTextPlugin'
import { CustomEase } from 'gsap/CustomEase'
import { MotionPathHelper } from 'gsap/MotionPathHelper'
// Register all plugins
gsap.registerPlugin(
ScrollTrigger,
Observer,
Draggable,
Flip,
ScrollToPlugin,
SplitText,
MorphSVGPlugin,
MotionPathPlugin,
DrawSVGPlugin,
ScrambleTextPlugin,
CustomEase,
MotionPathHelper
)
// Global configuration
gsap.defaults({
ease: 'power2.out',
duration: 1,
overwrite: 'auto'
})
// Ticker configuration
gsap.ticker.lagSmoothing(1000, 16)
// Custom ease definitions
CustomEase.create('smooth', 'M0,0 C0.5,0 0.5,1 1,1')
// Export configured gsap instance
export default gsap
Plugin Registration
Register Plugins
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { Draggable } from 'gsap/Draggable'
// Register all plugins at once
gsap.registerPlugin(ScrollTrigger, Draggable)
// Or register individually
gsap.registerPlugin(ScrollTrigger)
gsap.registerPlugin(Draggable)
Register with React Hook
import gsap from 'gsap'
import { useGSAP } from '@gsap/react'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
// Register hook and plugins
gsap.registerPlugin(useGSAP, ScrollTrigger)
Conditional Registration
import gsap from 'gsap'
// Only register needed plugins
const useScrollTrigger = true
const useDraggable = false
if (useScrollTrigger) {
import('gsap/ScrollTrigger').then(({ ScrollTrigger }) => {
gsap.registerPlugin(ScrollTrigger)
})
}
if (useDraggable) {
import('gsap/Draggable').then(({ Draggable }) => {
gsap.registerPlugin(Draggable)
})
}
Global Configuration
Defaults
// Set global defaults
gsap.defaults({
ease: 'power2.out',
duration: 1,
delay: 0,
overwrite: 'auto',
lazy: true
})
// Override defaults in individual tweens
gsap.to('.box', {
x: 200,
duration: 2, // Overrides default
ease: 'back.out(1.7)' // Overrides default
})
Timeline Defaults
const tl = gsap.timeline({
defaults: {
ease: 'power2.out',
duration: 1
},
paused: true,
repeat: -1,
yoyo: true
})
// All tweens in timeline inherit defaults
tl.to('.box1', { x: 100 }) // Uses defaults
.to('.box2', { x: 200, ease: 'back.out' }) // Overrides ease
ScrollTrigger Config
ScrollTrigger.config({
// Ignore mobile resize events (improves performance)
ignoreMobileResize: true,
// Custom auto-refresh events
autoRefreshEvents: 'visibilitychange,DOMContentLoaded,load',
// Default markers (development only)
defaultMarkers: false,
// Normalize scroll
normalizeScroll: true
})
Development Setup
Development Configuration
// gsap.dev.js
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
// Enable markers in development
if (process.env.NODE_ENV === 'development') {
ScrollTrigger.config({
defaultMarkers: true
})
// Log all tweens
gsap.registerEffect({
name: 'debugTween',
effect: (targets, config) => {
return gsap.to(targets, config)
},
extendTimeline: true
})
}
export { gsap }
Production Configuration
// gsap.prod.js
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
// Production optimizations
ScrollTrigger.config({
ignoreMobileResize: true,
autoRefreshEvents: 'visibilitychange,DOMContentLoaded,load'
})
// Disable markers
ScrollTrigger.config({
defaultMarkers: false
})
export { gsap }
Project Structure
Feature-Based Structure
src/
├── gsap/
│ ├── gsap.js # Central configuration
│ ├── animations.js # Reusable animations
│ └── constants.js # Eases, durations, etc.
├── components/
│ ├── Hero/
│ │ ├── Hero.jsx
│ │ └── heroAnimations.js
│ └── About/
│ ├── About.jsx
│ └── aboutAnimations.js
Animation Modules
// gsap/animations.js
import { gsap } from './gsap'
// Reusable entrance animation
export const entranceAnimation = (elements, options = {}) => {
return gsap.from(elements, {
opacity: 0,
y: 30,
stagger: 0.1,
duration: 0.8,
ease: 'power2.out',
...options
})
}
// Reusable hover animation
export const hoverAnimation = (element, options = {}) => {
const tl = gsap.timeline({ paused: true })
tl.to(element, {
scale: 1.1,
duration: 0.3,
ease: 'power2.out'
})
.to(element, {
scale: 1,
duration: 0.3,
ease: 'power2.out'
}, '+=0.5')
return tl
}
Environment Configuration
Development vs Production
// gsap/config.js
const isDevelopment = process.env.NODE_ENV === 'development'
export const config = {
// Enable debug tools in development
debug: isDevelopment,
// Performance optimizations
performance: !isDevelopment,
// Animation speed multiplier (for testing)
speedMultiplier: isDevelopment ? 0.5 : 1,
// Easing presets
eases: {
ui: 'power2.out',
entrance: 'back.out(1.7)',
exit: 'power2.in',
playful: 'elastic.out(1, 0.3)'
},
// Duration presets
durations: {
fast: 0.3,
normal: 0.8,
slow: 1.5
}
}
export default config
Best Practices
1. Register Plugins Once
// ✅ Register all plugins in one place
gsap.registerPlugin(ScrollTrigger, Draggable, Flip)
// ❌ Don't register multiple times
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger) // In one file
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger) // In another file - redundant!
2. Use Named Exports
// ✅ Use named exports for tree-shaking
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
// ❌ Avoid default imports when possible
import gsap from 'gsap' // Can't be tree-shaken as effectively
3. Centralize Configuration
// ✅ Central GSAP configuration
// gsap.js
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
gsap.defaults({ ease: 'power2.out', duration: 1 })
export default gsap
// Import configured gsap
import gsap from './gsap'
// ❌ Scattered configuration
import gsap from 'gsap'
gsap.defaults({ ease: 'power2.out' }) // In one file
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger) // In another file
4. Set Global Defaults
// ✅ Use defaults for consistency
gsap.defaults({
ease: 'power2.out',
duration: 1
})
// All tweens inherit these defaults
gsap.to('.box', { x: 200 })
gsap.from('.modal', { opacity: 0 })
// ❌ Repeating values
gsap.to('.box', { x: 200, ease: 'power2.out', duration: 1 })
gsap.from('.modal', { opacity: 0, ease: 'power2.out', duration: 1 })
5. Use Timelines for Sequences
// ✅ Use timeline for sequences
const tl = gsap.timeline()
tl.to('.box1', { x: 100 })
.to('.box2', { x: 100 })
.to('.box3', { x: 100 })
// Easy to control
tl.play()
tl.reverse()
tl.kill()
// ❌ Separate tweens
gsap.to('.box1', { x: 100, delay: 0 })
gsap.to('.box2', { x: 100, delay: 1 })
gsap.to('.box3', { x: 100, delay: 2 })
6. Clean Up Animations
// ✅ Clean up when component unmounts
function MyComponent() {
useGSAP(() => {
const tl = gsap.timeline()
tl.to('.box', { x: 200 })
// Automatically cleaned up
})
return <div className="box"></div>
}
// ❌ Memory leaks
function MyComponent() {
useEffect(() => {
const tl = gsap.timeline()
tl.to('.box', { x: 200 })
// Never cleaned up!
}, [])
return <div className="box"></div>
}
7. Test on Low-End Devices
// ✅ Performance considerations
gsap.to('.many-boxes', {
x: 100,
duration: 1,
ease: 'power2.out', // Simpler ease, better performance
stagger: 0.05, // Distribute load
onComplete: () => {
// Clean up when done
gsap.killTweensOf('.many-boxes')
}
})
// ❌ Too complex for low-end devices
gsap.to('.many-boxes', {
x: 100,
duration: 1,
ease: 'elastic.out(1, 0.3)', // Complex, slow
stagger: 0.01 // Too many tweens
})
8. Use Appropriate Eases
// ✅ Match ease to use case
gsap.from('.modal', {
opacity: 0,
scale: 0.8,
ease: 'back.out(1.7)', // Attention-grabbing entrance
duration: 0.5
})
// ❌ Wrong ease for context
gsap.from('.modal', {
opacity: 0,
scale: 0.8,
ease: 'elastic.out(1, 0.3)', // Too much for modal
duration: 0.5
})
9. Implement Responsive Animations
// ✅ Responsive with matchMedia
const mm = gsap.matchMedia()
mm.add('(min-width: 768px)', () => {
gsap.to('.box', { x: 200, duration: 1 })
})
mm.add('(max-width: 767px)', () => {
gsap.to('.box', { x: 100, duration: 1 })
})
// ❌ Not responsive
gsap.to('.box', { x: 200, duration: 1 }) // Same for all screens
10. Use Selectors Wisely
// ✅ Scoped selectors
const q = gsap.utils.selector('.container')
gsap.to(q('.box'), { x: 200 })
// Or in React
useGSAP(() => {
gsap.to('.box', { x: 200 })
}, { scope: container })
// ❌ Global selectors
gsap.to('.box', { x: 200 }) // Affects ALL .box elements
Common Mistakes
1. Not Registering Plugins
// ❌ Plugin won't work
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.to('.box', {
scrollTrigger: { trigger: '.box' }
})
// ✅ Register plugin first
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
gsap.to('.box', {
scrollTrigger: { trigger: '.box' }
})
2. Using Wrong Import Style
// ❌ Can't be tree-shaken
import gsap from 'gsap'
// ✅ Use named imports
import { gsap } from 'gsap'
3. Conflicting Tweens
// ❌ Two tweens fighting
gsap.to('.box', { x: 100, duration: 2 })
gsap.to('.box', { x: 200, duration: 1 })
// ✅ Use overwrite or kill first
gsap.to('.box', { x: 100, duration: 2, overwrite: true })
// Or
gsap.killTweensOf('.box', 'x')
gsap.to('.box', { x: 200, duration: 1 })
4. Forgetting Cleanup
// ❌ Memory leaks
useEffect(() => {
gsap.to('.box', { x: 200 })
}, [])
// ✅ Use useGSAP in React
useGSAP(() => {
gsap.to('.box', { x: 200 })
}, { scope: container })
5. Not Testing Performance
// ❌ Works on dev machine, slow on others
gsap.to('.many-complex-elements', {
filter: 'blur(10px)',
duration: 1
})
// ✅ Test and optimize
gsap.to('.many-complex-elements', {
opacity: 0.8, // Simpler property
duration: 1
})
Performance Checklist
- Register plugins once at app entry
- Use named exports for tree-shaking
- Set global defaults for consistency
- Use timelines for sequences
- Clean up animations when done
- Test on low-end devices
- Use appropriate eases
- Implement responsive animations
- Scope selectors to prevent conflicts
- Use transform properties over layout properties
- Stagger animations to distribute load
- Avoid filters on many elements
- Kill tweens before creating new ones
- Use ScrollTrigger toggleActions over scrub when possible
- Refresh ScrollTrigger after DOM changes
Quick Reference
| Task | Solution |
|---|---|
| Install GSAP | npm install gsap |
| Import core | import { gsap } from 'gsap' |
| Import plugin | import { ScrollTrigger } from 'gsap/ScrollTrigger' |
| Register plugins | gsap.registerPlugin(ScrollTrigger) |
| Set defaults | gsap.defaults({ ease, duration }) |
| CDN script | <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"> |
| React integration | npm install @gsap/react |
| React hook | import { useGSAP } from '@gsap/react' |
| Formerly members-only plugin | Install from gsap (v3.13+) and follow https://gsap.com/community/standard-license/ |
| Tree-shaking | Use named exports |
| Cleanup | useGSAP or manual kill() |
Weekly Installs
1
Repository
microck/gsap-skillsFirst Seen
6 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
warp1