Skip to content

[BUG] Layout shift caused by popLayout setting width without sub-pixel precision #3260

@reekystive

Description

@reekystive

2. Describe the bug

With AnimatePresence set to mode="popLayout", the exiting element’s geometry is captured and reapplied via inline styles.

If the element’s computed width or height contains sub-pixel values (e.g. 400.4 px), those dimensions are rounded to the nearest integer before the element is promoted to position:absolute.

The 1-pixel discrepancy introduces an immediate layout shift that is visible just before the exit transition starts.

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

https://codesandbox.io/p/sandbox/yz3wqg

Crucial code:

<motion.div
  className="outter-container"
  initial={false}
  // 400.5 will be rounded to 401 by AnimatePresence
  // 400.4 will be rounede to 400 by AnimatePresence
  animate={{ width: expand ? 400.4 : 200, height: 400 }}
>
  <AnimatePresence mode="popLayout">
    {expand && (
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        className="inner-container"
      >
        <div style={{ width: 200.2 }} className="inner-box"></div>
        <div style={{ width: 200.2 }} className="inner-box"></div>
      </motion.div>
    )}
  </AnimatePresence>
</motion.div>

4. Steps to reproduce

  1. Open the sandbox. The red-bordered container is rendered at 400.4 px wide.
  2. Press the space bar (or click the button) to trigger the exit animation.
  3. Watch the container jump by ±1 px in the first frame of the exit.

5. Expected behavior

AnimatePresence should preserve the exact sub-pixel dimensions it reads from getBoundingClientRect() when it applies width/height inline during popLayout, eliminating the layout shift.

6. Video or screenshots

Issue in real-world practice:

Note that the subpixel precision loss caused by the activation of AnimationPresence has led to text wrapping layout shift.

Screen.Capture.2025-06-13.at.12.47.38.mp4

Issue in provided sandbox:

Screen.Capture.2025-06-13.at.13.41.26.mp4

7. Environment details

  Package:
    motion: 12.17.3
    react: 19.1.0
    react-dom: 19.1.0
  System:
    OS: macOS 26.0
    CPU: (12) arm64 Apple M3 Pro
    Memory: 239.89 MB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Browsers:
    Chrome: 137.0.7151.104
    Chrome Canary: 139.0.7235.0
    Safari: 19.0
    Safari Technology Preview: 19.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions