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. This is 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, and your progress syncs across the web and the CoddyKit app. The React Academy course includes 4 lessons in total.
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. 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. The React Academy course includes 4 lessons in total.
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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
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