How To Fix Framer Motion AnimatePresence Collapse Leaving a Gap

Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
No comments yet. Be the first to comment.
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

You added overflow: hidden and the collapse still looks wrong. The problem is not the motion component. It is the gap on your parent flex container.
AnimatePresence keeps the exiting element mounted during the exit animation. It is still a flex child. Flex children still receive the parent gap even at height: 0.
You end up with an invisible ghost gap below your toggle while the panel animates out. That is the flicker.
Animate marginTop alongside height. Set it to negative the gap value on enter and exit. This cancels the gap exactly as height shrinks to zero.
// ❌ before — ghost gap remains after collapse
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
style={{ overflow: 'hidden' }}
>
// ✅ after — collapses cleanly
// marginTop: -40 cancels the parent gap-10 (40px) on exit
// marginTop: 0 when open — parent gap handles spacing normally
<motion.div
initial={{ height: 0, opacity: 0, marginTop: -40 }}
animate={{ height: 'auto', opacity: 1, marginTop: 0 }}
exit={{ height: 0, opacity: 0, marginTop: -40 }}
style={{ overflow: 'hidden' }}
>
Match -40 to whatever gap your parent uses.
// blur makes the expand and collapse feel nicer and less harsh
<motion.div
initial={{ height: 0, opacity: 0, marginTop: -40, filter: 'blur(8px)' }}
animate={{ height: 'auto', opacity: 1, marginTop: 0, filter: 'blur(0px)' }}
exit={{ height: 0, opacity: 0, marginTop: -40, filter: 'blur(8px)' }}
transition={{ duration: 0.3, ease: [0.25, 0.46, 0.45, 0.94] }}
style={{ overflow: 'hidden' }}
>
Flex gap does not care about height. A collapsed flex child is still a flex child. Animate the margin to match and the problem disappears.