Search code examples
cssreactjsframer-motion

Persisting position of draggable Framer Motion components


I'm creating a widget dashboard where you can move widgets around, and my aim is to persist the widgets' positions after they are dragged, so as to load them into the exact same place in future sessions.

Here's a codesandbox that illustrates the problem I am running into with framer-motion: https://codesandbox.io/p/sandbox/interesting-sun-p8h6cu.

The initial top and left values on a widget reflect its starting position correctly, but I'm having trouble persisting its new position after dragging it.

I'm updating the widget's position in the onDragEnd handler, which in turn updates the top and left styles on the widget. With framer-motion applying the drag with transform: translate and the update of the positioning styles, this results in a widget that:

  1. has its new position persisted correctly onDragEnd
  2. is shifted in the UI after the previous point, because the top + left styles are doubling the effect of the transform: translate drag styling.

I'm not sure how to tackle this problem. I've tried using transform: translate for the initial positioning, but it doesn't work. Plus, now I'm thinking that framer-motion would override it as soon as it gets dragged, resulting in a different unwanted behavior.

TLDR: I'm having trouble displaying absolutely positioned components that are draggable with framer-motion's drag feature


Solution

  • You're right that top and left are getting doubled up because the Framer drag functionality is altering the x and y. Since you then apply that xy transform to the top and left, you're getting unexpected results.

    If you instead only alter the x and y, everything should stay in sync.

    style={{ x: widget.x, y: widget.y }}
    

    instead of

    style={{ left: widget.x, top: widget.y }}