React / React Transitions / Framer Motion
Home /React /React Transitions /Framer Motion

Framer Motion

Framer Motion

Framer Motion is the most complete animation solution for React. It uses a declarative API where you describe the initial, animate, and exit states and the library handles interpolation, spring physics, and orchestration.

terminal
INSTALL

npm install framer-motion

6.1 Basic motion Component

FadeIn.jsx
JSX

import { motion } from 'framer-motion';

export function FadeIn({ children }) {
  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -20 }}
      transition={{ duration: 0.4, ease: 'easeOut' }}
    >
      {children}
    </motion.div>
  );
}

6.2 AnimatePresence:  Exit Animations

AnimatePresence is Framer Motion’s answer to the unmount problem. Wrap conditional or list components with it to enable exit animations.

Notification.jsx
JSX

import { AnimatePresence, motion } from 'framer-motion';

export function NotificationStack({ notifications }) {
  return (
    <div className="stack">
      <AnimatePresence>
        {notifications.map(n => (
          <motion.div
            key={n.id}
            layout                   {/* auto-animates layout shifts */}
            initial={{ opacity: 0, x: 60, scale: 0.9 }}
            animate={{ opacity: 1, x: 0, scale: 1 }}
            exit={{ opacity: 0, x: 60, scale: 0.85 }}
            transition={{ type: 'spring', stiffness: 500, damping: 40 }}
            className="notification"
          >
            {n.message}
          </motion.div>
        ))}
      </AnimatePresence>
    </div>
  );
}

6.3 Variants: Orchestrated Animations

Variants let you define named states and propagate them down the component tree — enabling staggered child animations with a single parent state change.

StaggerList.jsx
JSX

import { motion } from 'framer-motion';

const container = {
  hidden: {},
  show: {
    transition: {
      staggerChildren: 0.1,    // 100ms between each child
      delayChildren: 0.2,
    },
  },
};

const item = {
  hidden: { opacity: 0, y: 24 },
  show: {
    opacity: 1,
    y: 0,
    transition: { type: 'spring', bounce: 0.35 },
  },
};

export function StaggerList({ items }) {
  return (
    <motion.ul
      variants={container}
      initial="hidden"
      animate="show"
    >
      {items.map(item => (
        <motion.li key={item.id} variants={item}>
          {item.text}
        </motion.li>
      ))}
    </motion.ul>
  );
}

6.4 Layout Animations

Add layout prop to a motion component and Framer Motion automatically animates any change in its size or position, including reflows caused by sibling DOM changes.

ExpandableCard.jsx
JSX

import { motion } from 'framer-motion';
import { useState } from 'react';

export function ExpandableCard({ title, body }) {
  const [expanded, setExpanded] = useState(false);

  return (
    <motion.div
      layout                         {/* animates height changes */}
      onClick={() => setExpanded(e => !e)}
      style={{ cursor: 'pointer', overflow: 'hidden' }}
    >
      <motion.h3 layout="position">{title}</motion.h3>
      {expanded && (
        <motion.p
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
        >
          {body}
        </motion.p>
      )}
    </motion.div>
  );
}

6.5 Page Transitions with React Router

PageWrapper.jsx
JSX

import { motion, AnimatePresence } from 'framer-motion';
import { useLocation, Routes, Route } from 'react-router-dom';

const pageVariants = {
  initial:  { opacity: 0, x: -20 },
  animate:  { opacity: 1, x: 0 },
  exit:     { opacity: 0, x: 20 },
};

const pageTransition = { duration: 0.25, ease: 'easeInOut' };

export function AnimatedRoutes() {
  const location = useLocation();

  return (
    <AnimatePresence mode="wait">
      <Routes location={location} key={location.pathname}>
        <Route path="/" element={
          <motion.div
            variants={pageVariants}
            initial="initial"
            animate="animate"
            exit="exit"
            transition={pageTransition}
          >
            <HomePage />
          </motion.div>
        } />
      </Routes>
    </AnimatePresence>
  );
}