Animation20 min read
Advanced Animation Techniques: Framer Motion and GSAP Mastery
Master advanced animation techniques using Framer Motion and GSAP to create stunning, performant animations.
Animations bring websites to life, creating engaging user experiences. This comprehensive guide covers advanced techniques using Framer Motion and GSAP.
Framer Motion Fundamentals
Basic Animations
typescript
import { motion } from 'framer-motion';
export function AnimatedCard() {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
Content
</motion.div>
);
}Stagger Animations
typescript
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.1,
},
},
};
const item = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 },
};
<motion.div variants={container} initial="hidden" animate="show">
{items.map((item) => (
<motion.div key={item.id} variants={item}>
{item.content}
</motion.div>
))}
</motion.div>Scroll Animations
typescript
import { useInView } from 'framer-motion';
import { useRef } from 'react';
export function ScrollAnimation() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true });
return (
<motion.div
ref={ref}
initial={{ opacity: 0, x: -50 }}
animate={isInView ? { opacity: 1, x: 0 } : { opacity: 0, x: -50 }}
transition={{ duration: 0.5 }}
>
Content
</motion.div>
);
}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' });
},
});Combining Framer Motion and GSAP
typescript
// Use Framer Motion for component animations
// Use GSAP for complex timeline animations
export function HybridAnimation() {
const [isVisible, setIsVisible] = useState(false);
const containerRef = useRef(null);
// GSAP for complex sequence
useGSAP(() => {
if (isVisible) {
gsap.to('.complex-element', {
rotation: 360,
scale: 1.2,
duration: 2,
ease: 'elastic.out(1, 0.3)',
});
}
}, { scope: containerRef, dependencies: [isVisible] });
// Framer Motion for simple interactions
return (
<motion.div
ref={containerRef}
onViewportEnter={() => setIsVisible(true)}
>
<motion.button whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }}>
Click Me
</motion.button>
</motion.div>
);
}Best Practices
- 1. Performance: Use
transformandopacityfor animations - 2. Accessibility: Respect
prefers-reduced-motion - 3. Mobile: Optimize for touch interactions
- 4. Testing: Test animations across devices
typescript
// Respect reduced motion
const prefersReducedMotion = useReducedMotion();
const animation = prefersReducedMotion
? {}
: {
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
};Create stunning, performant animations that enhance user experience.