Layout Animations & AnimatePresence
Animate layout changes automatically with layout prop and mount/unmount with AnimatePresence.
Layout Animations & AnimatePresence is a free React Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Layout Animations
Add the layout prop to a motion component and Framer Motion automatically animates any layout changes (size, position) caused by state or DOM mutations — no manual positioning needed.
<motion.div layout style={{ width: isExpanded ? 300 : 150 }}>
{/* Width animates smoothly when isExpanded changes */}
</motion.div>Layout Prop Values
The layout prop accepts true (all layout), 'position' (position only), or 'size' (size only) to limit what's animated.
<motion.div layout="position"> {/* only x/y positions animate */}
<motion.div layout="size"> {/* only width/height animate */}layoutId for Shared Element Transitions
Give two elements the same layoutId and Framer Motion will animate between them as if they're the same element, even across different components.
// Thumbnail in list:
<motion.img layoutId={`photo-${id}`} src={src} className="thumbnail" />
// Full-screen view:
<motion.img layoutId={`photo-${id}`} src={src} className="fullscreen" />
// Framer Motion morphs one into the other automaticallyAnimatePresence
AnimatePresence enables exit animations. Without it, unmounting components disappear instantly. Wrap a conditional render with it to animate unmounts.
import { AnimatePresence, motion } from 'framer-motion';
<AnimatePresence>
{isVisible && (
<motion.div
key="notification"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
/>
)}
</AnimatePresence>The key Prop is Required
AnimatePresence needs each child to have a stable key. Without a unique key, React can't detect when elements unmount vs when they update.
// Animating between pages:
<AnimatePresence mode="wait">
<motion.div key={pathname} ... />
</AnimatePresence>AnimatePresence mode
mode controls how outgoing and incoming elements overlap. 'wait' delays the enter animation until the exit completes. 'sync' (default) runs both simultaneously.
// Page transitions — wait for old page to exit:
<AnimatePresence mode="wait">
<motion.main key={pathname} ... />
</AnimatePresence>
// Toast stack — new toasts appear while old ones exit:
<AnimatePresence mode="sync">
{toasts.map(t => <motion.div key={t.id} ... />)}
</AnimatePresence>Animating Lists with Layout
Combine layout and AnimatePresence to animate list items reordering and removal.
<motion.ul>
<AnimatePresence>
{items.map(item => (
<motion.li
key={item.id}
layout
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
>
{item.name}
</motion.li>
))}
</AnimatePresence>
</motion.ul>LayoutGroup
LayoutGroup coordinates layout animations across multiple independent motion components so they animate together as one group.
import { LayoutGroup } from 'framer-motion';
<LayoutGroup>
<Sidebar />
<MainContent />
{/* Both animate layout changes together */}
</LayoutGroup>Correcting Layout Distortion
Layout animations can distort borders, shadows, and border-radius. Use the layoutDependency prop or CSS scale correction to fix visual artifacts.
<motion.div
layout
style={{ borderRadius: 12 }}
// Framer Motion auto-corrects border-radius during scale changes
/>Shared Axis Transition Pattern
For wizard steps or tabs, animate X position based on direction to create a meaningful spatial relationship between screens.
const variants = {
enter: (dir: number) => ({ x: dir > 0 ? '100%' : '-100%', opacity: 0 }),
center: { x: 0, opacity: 1 },
exit: (dir: number) => ({ x: dir < 0 ? '100%' : '-100%', opacity: 0 }),
};
<AnimatePresence custom={direction} mode="wait">
<motion.div
key={step}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
/>
</AnimatePresence>Quick Check
Which AnimatePresence mode delays the enter animation until the exit animation completes?
Recap
layout animates size/position changes automatically. layoutId morphs between two elements across the tree. AnimatePresence enables exit animations — always give children stable key props and choose mode='wait' for page transitions.
Frequently asked questions
Is the “Layout Animations & AnimatePresence” lesson free?
Yes — the full text of “Layout Animations & AnimatePresence” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “Layout Animations & AnimatePresence”?
Animate layout changes automatically with layout prop and mount/unmount with AnimatePresence. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Layout Animations & AnimatePresence” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Motion Components & Basic Animations
- Variants for Orchestrated Animations
- Gesture Animations: Hover, Tap & Drag
- Layout Animations & AnimatePresence