# How To Fix Framer Motion AnimatePresence Collapse Leaving a Gap

# Introduction

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.

# What is happening

`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.

# The fix

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.

```jsx
// ❌ 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' }}
>
```

```jsx
// ✅ 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.

# Bonus — add blur

```jsx
// 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.
