Skip to main content
Course/Module 8/Topic 3 of 4Intermediate

Framer Motion

Learn Framer Motion for creating smooth animations and transitions in React applications

85 minBy Priygop TeamLast updated: Feb 2026

What is Framer Motion?

Framer Motion is a production-ready motion library for React. It provides a simple API for creating animations, gestures, and drag interactions.

Basic Animations

Example
// Install Framer Motion
npm install framer-motion

// Basic animations
import { motion } from 'framer-motion';

function BasicAnimations() {
    return (
        <div>
            {/* Fade in animation */}
            <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                transition={{ duration: 0.5 }}
            >
                <h1>Welcome to our app!</h1>
            </motion.div>

            {/* Slide in from left */}
            <motion.div
                initial={{ x: -100, opacity: 0 }}
                animate={{ x: 0, opacity: 1 }}
                transition={{ duration: 0.8, ease: "easeOut" }}
            >
                <p>This content slides in from the left</p>
            </motion.div>

            {/* Scale animation */}
            <motion.button
                whileHover={{ scale: 1.1 }}
                whileTap={{ scale: 0.9 }}
                transition={{ type: "spring", stiffness: 400, damping: 17 }}
            >
                Click me!
            </motion.button>

            {/* Staggered animations */}
            <motion.ul
                initial="hidden"
                animate="visible"
                variants={{
                    hidden: { opacity: 0 },
                    visible: {
                        opacity: 1,
                        transition: {
                            staggerChildren: 0.1
                        }
                    }
                }}
            >
                {['Item 1', 'Item 2', 'Item 3', 'Item 4'].map((item, index) => (
                    <motion.li
                        key={index}
                        variants={{
                            hidden: { opacity: 0, y: 20 },
                            visible: { opacity: 1, y: 0 }
                        }}
                    >
                        {item}
                    </motion.li>
                ))}
            </motion.ul>
        </div>
    );
}

// Animated card component
function AnimatedCard({ children }) {
    return (
        <motion.div
            initial={{ opacity: 0, y: 50 }}
            animate={{ opacity: 1, y: 0 }}
            whileHover={{ 
                y: -10,
                boxShadow: "0 20px 40px rgba(0,0,0,0.1)"
            }}
            transition={{ 
                duration: 0.3,
                ease: "easeOut"
            }}
            style={{
                padding: '20px',
                border: '1px solid #ddd',
                borderRadius: '8px',
                backgroundColor: 'white'
            }}
        >
            {children}
        </motion.div>
    );
}

// Usage
function CardGrid() {
    const cards = [
        { id: 1, title: 'Card 1', content: 'This is the first card' },
        { id: 2, title: 'Card 2', content: 'This is the second card' },
        { id: 3, title: 'Card 3', content: 'This is the third card' },
    ];

    return (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '20px' }}>
            {cards.map((card, index) => (
                <AnimatedCard key={card.id}>
                    <h3>{card.title}</h3>
                    <p>{card.content}</p>
                </AnimatedCard>
            ))}
        </div>
    );
}

Advanced Animations

Example
// Advanced Framer Motion features
import { motion, AnimatePresence } from 'framer-motion';

// Page transitions
function PageTransition({ children }) {
    return (
        <motion.div
            initial={{ opacity: 0, x: 100 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: -100 }}
            transition={{ duration: 0.5 }}
        >
            {children}
        </motion.div>
    );
}

// Modal with backdrop
function AnimatedModal({ isOpen, onClose, children }) {
    return (
        <AnimatePresence>
            {isOpen && (
                <>
                    <motion.div
                        initial={{ opacity: 0 }}
                        animate={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                        onClick={onClose}
                        style={{
                            position: 'fixed',
                            top: 0,
                            left: 0,
                            right: 0,
                            bottom: 0,
                            backgroundColor: 'rgba(0, 0, 0, 0.5)',
                            zIndex: 1000,
                        }}
                    />
                    <motion.div
                        initial={{ opacity: 0, scale: 0.8, y: 50 }}
                        animate={{ opacity: 1, scale: 1, y: 0 }}
                        exit={{ opacity: 0, scale: 0.8, y: 50 }}
                        transition={{ type: "spring", damping: 25, stiffness: 300 }}
                        style={{
                            position: 'fixed',
                            top: '50%',
                            left: '50%',
                            transform: 'translate(-50%, -50%)',
                            backgroundColor: 'white',
                            padding: '20px',
                            borderRadius: '8px',
                            zIndex: 1001,
                            minWidth: '300px',
                        }}
                    >
                        {children}
                    </motion.div>
                </>
            )}
        </AnimatePresence>
    );
}

// Drag and drop
function DraggableItem({ id, children }) {
    return (
        <motion.div
            drag
            dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0 }}
            dragElastic={0.1}
            whileDrag={{ scale: 1.1, boxShadow: "0 10px 20px rgba(0,0,0,0.2)" }}
            style={{
                padding: '10px',
                border: '1px solid #ddd',
                borderRadius: '4px',
                backgroundColor: 'white',
                cursor: 'grab',
            }}
        >
            {children}
        </motion.div>
    );
}

// Gesture animations
function GestureExample() {
    return (
        <motion.div
            whileHover={{ scale: 1.05 }}
            whileTap={{ scale: 0.95 }}
            drag="x"
            dragConstraints={{ left: -100, right: 100 }}
            dragElastic={0.2}
            onDragEnd={(event, info) => {
                console.log('Drag ended:', info);
            }}
            style={{
                width: '100px',
                height: '100px',
                backgroundColor: '#ff6b6b',
                borderRadius: '50%',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                color: 'white',
                cursor: 'grab',
            }}
        >
            Drag me!
        </motion.div>
    );
}

// Layout animations
function LayoutAnimation() {
    const [items, setItems] = useState([1, 2, 3, 4, 5]);

    const addItem = () => {
        setItems([...items, items.length + 1]);
    };

    const removeItem = (index) => {
        setItems(items.filter((_, i) => i !== index));
    };

    return (
        <div>
            <button onClick={addItem}>Add Item</button>
            <motion.div layout>
                {items.map((item, index) => (
                    <motion.div
                        key={item}
                        layout
                        initial={{ opacity: 0, scale: 0.8 }}
                        animate={{ opacity: 1, scale: 1 }}
                        exit={{ opacity: 0, scale: 0.8 }}
                        transition={{ duration: 0.3 }}
                        style={{
                            padding: '10px',
                            margin: '5px',
                            backgroundColor: '#f0f0f0',
                            borderRadius: '4px',
                            display: 'flex',
                            justifyContent: 'space-between',
                            alignItems: 'center',
                        }}
                    >
                        <span>Item {item}</span>
                        <button onClick={() => removeItem(index)}>Remove</button>
                    </motion.div>
                ))}
            </motion.div>
        </div>
    );
}

// Scroll-triggered animations
function ScrollAnimation() {
    return (
        <motion.div
            initial={{ opacity: 0, y: 100 }}
            whileInView={{ opacity: 1, y: 0 }}
            viewport={{ once: true, amount: 0.3 }}
            transition={{ duration: 0.8 }}
            style={{
                padding: '40px',
                backgroundColor: '#f8f9fa',
                margin: '20px 0',
                borderRadius: '8px',
            }}
        >
            <h2>This animates when scrolled into view</h2>
            <p>This content will animate when it comes into the viewport.</p>
        </motion.div>
    );
}

Additional Resources

Recommended Reading

  • React Query Documentation
  • React Hook Form Guide
  • Framer Motion Tutorial

Online Resources

  • React Ecosystem Overview
  • Popular React Libraries
  • React Query Best Practices
Chat on WhatsApp
Priygop - Leading Professional Development Platform | Expert Courses & Interview Prep