Animating React Component Size Changes with Framer Motion's layout Prop
Learn how Framer Motion’s layout prop animates width and height changes with the FLIP technique, plus a ready‑to‑run toggle box example and performance tips.
03 Jul 2026, 00:42 UTC

Why size changes feel abrupt
When a React component’s width or height changes on re‑render, the browser repaints the element instantly. Users see a jump rather than a smooth transition, which can feel jarring especially in dashboards or modal panels that resize based on user input.
How the layout prop smooths them
Framer Motion’s layout flag activates the FLIP (First, Last, Invert, Play) technique under the hood. When the flag is present, Motion captures the element’s layout before and after a render, then animates the difference using CSS transforms. Because transforms do not affect document flow, the browser avoids layout thrashing and can run the animation on the compositor thread.
The prop works alongside transition for fine‑grained timing, and with layoutId for shared‑element animations across different parts of the tree. When wrapped in AnimatePresence, exiting elements keep their layout animation, enabling coordinated enter/leave effects.
Worked example: toggling a box size
Below is a minimal React component that toggles a box between two sizes when clicked. Copy it into a file such as src/ToggleBox.jsx in a project that already has framer-motion@^6.0.0 installed.
import { motion, AnimatePresence } from 'framer-motion';
import { useState } from 'react';
export default function ToggleBox() {
const [big, setBig] = useState(false);
return (
setBig(!big)}
style={{ cursor: 'pointer' }}
/>
);
}
Where to run: start your React dev server (npm start or yarn dev) and navigate to the route that renders ToggleBox. No special permissions are required; the component runs in the browser.
Expected checks: after clicking the box, you should see it grow or shrink smoothly rather than snapping. Open React DevTools → Profiler, record a click, and verify that the commit shows minimal “Layout” work (the bar for forced synchronous layout should stay low). If you notice a spike, consider reducing the number of simultaneously animating large elements.
Limitations and practical verification:
- Performance cost: animating many large components at once can drop frames. Mitigate by limiting concurrent layout animations or using
layoutonly on elements that truly need it. - SSR incompatibility: layout animations run after hydration, so the initial server‑rendered markup appears without animation. This is expected; you can gate the animation with a
useEffectthat sets a state flag after mount if you need to avoid a flash of static content. - Verification: besides visual inspection, use the Chrome DevTools “Performance” panel to look for long frames (>16 ms) during the interaction. If frames stay under the threshold, the animation is likely smooth.
Actionable closing
If you notice abrupt size changes in your UI, add the layout prop to the moving element and pair it with a spring or tween transition that matches your design language. Test with the React Profiler and Chrome Performance tools to ensure the animation stays lightweight. For shared‑element transitions, introduce layoutId and keep the elements within the same AnimatePresence tree for the best results.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.