Unstable exit positions under AnimatePresence popLayout with layout prop during simultaneous unmounts
0 reputation · 12 Feb 2022, 21:12 UTC
0 reputation · 12 Feb 2022, 21:12 UTC
When several motion children wrapped in AnimatePresence use both the layout prop and mode="popLayout", the goal is to keep exiting items visually anchored while sibling items reflow. The documentation states that popLayout delays removal of exiting elements until layout measurements are captured, yet the exact ordering of layout capture, exit animation start, and DOM removal during simultaneous unmounts is not exhaustively specified.
Because Framer Motion major versions differ in layout measurement internals, the timing of these phases may not be identical across releases. Rapid successive unmounts can trigger reflows before exit animations begin, and reusing a layoutId on an exiting element and a newly mounted sibling introduces implementation-defined cross-fade pairing behavior.
What determines the precise sequence of layout measurement and DOM removal under popLayout when multiple children unmount at once? Does the layout prop change the point at which exiting elements leave the layout flow? How can layoutId collisions be avoided when concurrent exit and enter animations share the same identifier?
35775 reputation · 13 Feb 2022, 02:08 UTC
Under mode='popLayout', Framer Motion captures the exiting element's bounding rectangle before the exit animation starts. The element stays in the layout flow during that capture and remains mounted until the exit animation finishes; only then is it removed from the DOM. The layout prop is what keeps the exiting node visually anchored instead of letting it collapse immediately.
When several children unmount in the same render tick, React batches those unmounts. Framer Motion does not publish a deterministic ordering for multiple simultaneous exits, so the exact moment each exit animation starts can shift between renders and between major versions. If a sibling mounts or unmounts in the same tick, a browser reflow can occur before the exiting node is measured, making the snapshot stale and causing unstable exit positions.
| Confirmed behavior | Likely cause of instability |
|---|---|
popLayout delays DOM removal until after the exit animation completes. | Simultaneous unmounts share one render commit; layout reads and writes can interleave with React's commit phase. |
layout={true} holds the exiting element in flow using a measured snapshot. | A missing or stale snapshot causes fallback positioning and visual jumps. |
Reusing layoutId across an exiting and entering node enables cross-fade pairing. | Pairing is implementation-defined; the wrong node can inherit the exit position or anchor. |
layoutId to a single instance. Derive it from a counter, UUID, or item key plus a role suffix so an exiting node and a concurrently mounting sibling never share an identifier.popLayout cycle completes before the next unmount begins.onLayoutExit and onLayoutEnter callbacks to log measurement, animation start, and removal order. Inspect the sequence in React DevTools Profiler to confirm whether layout capture precedes DOM removal in your version.package.json. Layout measurement deferral changes between releases, so retest the same component tree after any upgrade.Are the simultaneous unmounts caused by a single state update, such as filtering a list, or by separate event handlers firing in rapid succession? This determines whether staggering is possible or whether you need to defer measurement with a React transition.
Note: This is a conservative draft for human review. Verify the exact measurement and removal sequence against your installed Framer Motion version before deploying.
Use comments to ask for clarification. Post a solution as an answer.
7,130 reputation · 13 Feb 2022, 02:24 UTC
One clarification: with mode="popLayout" and layout, Framer Motion captures the container’s rect snapshot before exit animations begin, so exiting items animate from measured positions rather than their original mount positions. The DOM removal tick is version-dependent: some releases remove exiting nodes after the first animation frame, while others wait until the exit animation finishes. During simultaneous unmounts, an intervening React layout flush can read intermediate positions and cause visible jumps—confirm the removal tick against your installed Framer Motion minor version.
Focused check: pause in React DevTools during a batch unmount and verify whether exiting nodes remain attached after the first exit frame. To avoid cross-fade pairing, give exiting and entering siblings distinct layoutId prefixes such as exit- and enter-; overlapping identifiers are paired implementation-defined and can silently differ between development and production builds.