#3805·motion

[BUG] `snapToCursor` accumulates position drift on repeated drags with initial coordinates

Author: jaysin586Created Sep 8, 2026Updated Sep 8, 2026

Description

We discovered this while testing React Motion parity in @humanspeak/svelte-motion. After noticing repeated snap-to-cursor drift in our Svelte implementation, we independently reproduced the same behavior using public React Motion APIs.

When an element has initial x/y coordinates, the first controlled drag snaps correctly. Subsequent starts progressively offset the element from the pointer.

Reproduction

StackBlitz reproduction

The example uses:

javascript
const controls = useDragControls();

<button
  onPointerDown={(event) =>
    controls.start(event, { snapToCursor: true })
  }
>
  Start Initial Drag
</button>

<motion.div
  drag
  dragControls={controls}
  dragListener={false}
  dragMomentum={false}
  initial={{ x: 100, y: 40 }}
/>

Steps to reproduce

  1. Press and hold Start Initial Drag.
  2. Move the pointer approximately 150 pixels right and 50 pixels down.
  3. Release.
  4. Repeat the same gesture from the button several times.

Expected behavior

Every pointerdown should center the element beneath the pointer, regardless of its previous position. Repeating the same gesture should produce the same final position.

Actual behavior

Subsequent starts accumulate an offset. The element drifts upward and away from the pointer instead of centering beneath it.

Versions

  • motion, framer-motion, motion-dom: 13.2.0
  • react, react-dom: 19.1.1
  • Reproduced in Chromium.

Investigation

The snap calculation appears to combine a stored projection layout measurement with the changing current motion value, causing the correction to accumulate across sessions.

This may be related to #3445, which addressed first-drag snapping with initial coordinates. We haven’t bisected the history to establish when the repeated-start behavior was introduced.

We have a failing real-browser regression test in our Svelte repository and would be happy to contribute a focused upstream fix with browser regression coverage.