Animation20 min read
Advanced Animation Techniques: GSAP & ScrollTrigger Mastery
Master GSAP timelines, ScrollTrigger, and scroll-linked motion for stunning, performant web animations.
Animations bring websites to life, creating engaging user experiences. This guide covers production-ready GSAP patterns for React and Next.js.
GSAP in React
Basic reveal on mount
typescript
import gsap from 'gsap';
import { useGSAP } from '@/hooks/useGSAP';
export function AnimatedCard() {
const ref = useGSAP(() => {
gsap.fromTo(ref.current,
{ opacity: 0, y: 20, scale: 0.98 },
{ opacity: 1, y: 0, scale: 1, duration: 0.6, ease: 'power3.out' }
);
}, []);
return <div ref={ref} className="card opacity-0">Content</div>;
}Stagger children
typescript
useGSAP(() => {
gsap.from('[data-reveal-item]', {
opacity: 0,
y: 24,
duration: 0.6,
stagger: 0.1,
ease: 'power3.out',
});
}, []);Scroll-triggered reveals
typescript
import { useGsapReveal } from '@/hooks/useGsapReveal';
export function ScrollSection() {
const ref = useGsapReveal({ preset: 'fadeLeft', stagger: 0.12 });
return (
<section ref={ref}>
{items.map((item) => (
<div key={item.id} data-reveal-item className="opacity-0">
{item.content}
</div>
))}
</section>
);
}GSAP Advanced Techniques
Timeline Animations
typescript
import { useGSAP } from '@/hooks/useGSAP';
import gsap from 'gsap';
export function TimelineAnimation() {
const containerRef = useRef(null);
useGSAP(() => {
const tl = gsap.timeline();
tl.from('.title', {
opacity: 0,
y: -50,
duration: 1,
ease: 'power3.out',
})
.from('.subtitle', {
opacity: 0,
x: -30,
duration: 0.8,
}, '-=0.5')
.from('.content', {
opacity: 0,
y: 30,
duration: 1,
stagger: 0.1,
}, '-=0.3');
}, { scope: containerRef });
return <div ref={containerRef}>...</div>;
}ScrollTrigger Animations
typescript
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
useGSAP(() => {
gsap.fromTo('.element',
{
opacity: 0,
y: 100,
},
{
opacity: 1,
y: 0,
duration: 1,
scrollTrigger: {
trigger: '.element',
start: 'top 80%',
end: 'bottom 20%',
toggleActions: 'play none none reverse',
},
}
);
}, {});Performance Optimization
typescript
// Use will-change for better performance
gsap.set('.animated', {
willChange: 'transform, opacity',
});
// Clean up after animation
gsap.to('.element', {
opacity: 0,
onComplete: () => {
gsap.set('.element', { willChange: 'auto' });
},
});Hover and interaction with GSAP
typescript
const btnRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
const el = btnRef.current;
if (!el) return;
const onEnter = () => gsap.to(el, { scale: 1.05, duration: 0.2, ease: 'power2.out' });
const onLeave = () => gsap.to(el, { scale: 1, duration: 0.2, ease: 'power2.out' });
const onDown = () => gsap.to(el, { scale: 0.95, duration: 0.1 });
const onUp = () => gsap.to(el, { scale: 1.05, duration: 0.1 });
el.addEventListener('mouseenter', onEnter);
el.addEventListener('mouseleave', onLeave);
el.addEventListener('mousedown', onDown);
el.addEventListener('mouseup', onUp);
return () => {
el.removeEventListener('mouseenter', onEnter);
el.removeEventListener('mouseleave', onLeave);
el.removeEventListener('mousedown', onDown);
el.removeEventListener('mouseup', onUp);
};
}, []);Best Practices
- 1. Performance: Animate
transformandopacityonly when possible - 2. Accessibility: Respect
prefers-reduced-motion - 3. Cleanup: Use
gsap.context()and revert on unmount - 4. Testing: Test scroll scenes on mobile and desktop
typescript
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
gsap.set('.animated', { opacity: 1, clearProps: 'all' });
return;
}Create stunning, performant animations that enhance user experience.