Creating Beautiful UI Animations with Framer Motion
Learn how to create engaging animations in your React applications using Framer Motion, a powerful library that makes animations easy and fun.
Introduction to Framer Motion
Framer Motion is a production-ready motion library for React that makes it easy to create beautiful animations with a simple and powerful API.
Key Features
- Simple and intuitive API
- Production-ready performance
- Gesture animations
- Layout animations
- SVG animations
- CSS variables support
Getting Started
First, install Framer Motion:
npm install framer-motion
# or
yarn add framer-motion
Basic Animations
1. Simple Animations
Basic fade-in animation:
import { motion } from 'framer-motion';
function FadeIn() {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
>
Hello World!
</motion.div>
);
}
2. Hover and Tap Animations
Create interactive elements:
function InteractiveButton() {
return (
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
Click me!
</motion.button>
);
}
3. Variants
Organize animations with variants:
const cardVariants = {
hidden: { opacity: 0, y: 20 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.5,
ease: "easeOut"
}
}
};
function Card() {
return (
<motion.div
variants={cardVariants}
initial="hidden"
animate="visible"
>
Card Content
</motion.div>
);
}
Advanced Techniques
1. Gesture Animations
Create drag-and-drop interfaces:
function DraggableItem() {
return (
<motion.div
drag
dragConstraints={{
top: -50,
left: -50,
right: 50,
bottom: 50,
}}
whileDrag={{ scale: 1.1 }}
>
Drag me!
</motion.div>
);
}
2. Layout Animations
Smooth layout changes:
function ExpandingCard() {
const [isExpanded, setIsExpanded] = useState(false);
return (
<motion.div
layout
onClick={() => setIsExpanded(!isExpanded)}
style={{
borderRadius: 10,
backgroundColor: "#fff",
cursor: "pointer"
}}
>
<motion.h2 layout="position">
Click to expand
</motion.h2>
{isExpanded && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
>
Extra content here
</motion.div>
)}
</motion.div>
);
}
3. Scroll Animations
Create scroll-triggered animations:
function ScrollAnimation() {
return (
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
>
This animates when scrolled into view
</motion.div>
);
}
4. SVG Animations
Animate SVG paths:
function AnimatedLogo() {
return (
<motion.svg
width="100"
height="100"
viewBox="0 0 100 100"
>
<motion.path
d="M0 50L100 50"
stroke="#000"
strokeWidth={2}
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
transition={{ duration: 2 }}
/>
</motion.svg>
);
}
Performance Optimization
1. Use Layout Animation Carefully
// Instead of animating everything
<motion.div layout>
{items.map(item => (
<div key={item.id}>{item.content}</div>
))}
</motion.div>
// Animate specific properties
<div>
{items.map(item => (
<motion.div
key={item.id}
layout="position"
>
{item.content}
</motion.div>
))}
</div>
2. Optimize Re-renders
Use AnimatePresence
efficiently:
function OptimizedList({ items }) {
return (
<AnimatePresence mode="popLayout">
{items.map(item => (
<motion.div
key={item.id}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{item.content}
</motion.div>
))}
</AnimatePresence>
);
}
Best Practices
-
Performance
- Use
layout
animations sparingly - Optimize heavy animations
- Use hardware acceleration when needed
- Use
-
User Experience
- Keep animations subtle
- Respect user preferences
- Provide fallbacks
-
Accessibility
- Respect reduced motion settings
- Ensure keyboard navigation
- Maintain focus management
Common Patterns
1. Page Transitions
const pageVariants = {
initial: { opacity: 0, x: -200 },
enter: { opacity: 1, x: 0 },
exit: { opacity: 0, x: 200 }
};
function Page() {
return (
<motion.div
variants={pageVariants}
initial="initial"
animate="enter"
exit="exit"
>
Page Content
</motion.div>
);
}
2. Loading States
function LoadingSpinner() {
return (
<motion.div
animate={{
rotate: 360
}}
transition={{
duration: 1,
repeat: Infinity,
ease: "linear"
}}
>
⚪
</motion.div>
);
}
Conclusion
Framer Motion provides a powerful toolkit for creating beautiful animations in React. Remember these key points:
- Start with simple animations
- Use variants for complex sequences
- Optimize performance
- Consider accessibility
- Test on different devices
With these techniques, you can create engaging user experiences that delight your users while maintaining performance and accessibility.
Happy animating! 🎨