Skip to content

Incorrect widget position when parent is scaled with CSS transform (drift after refresh) #977

Open

Description

@c3aus3scu

Hi! First of all, thank you for maintaining react-rnd — it’s an amazing tool and a key part of my streaming/donation platform project.

I'm facing a consistent issue that seems related to how react-rnd computes positions when the parent container is scaled using CSS transforms.

The problem

When placing the element inside a scaled parent:

transform: scale(0.7); transform-origin: top left;

…the widget moves a few pixels after refresh, even though:

I store the exact x, y, width, height in the database,

I pass them back into the position and size props,

scale={0.7} is correctly passed into .

Expected

The widget should appear in the exact same logical position (1920x1080 coordinate system) before and after refresh.

Actual

After the first refresh, the widget shifts slightly (down/right), usually by a few pixels.

After the second refresh, it stabilizes and no longer moves.

This only happens when the canvas preview uses CSS transform scale.

Environment

React 18

react-rnd latest (10.x)

Vite

Canvas preview uses transform scaling for OBS-like overlay editor

scale prop is always provided to

<div style={{ transform: scale(${scale})`,
transformOrigin: "top left",
width: 1920,
height: 1080,
position: "relative"
}}

<Rnd
scale={scale}
bounds=".canvas-area"
position={{ x, y }}
size={{ width, height }}
onDragStop={(e, d) => onUpdate({ x: d.x, y: d.y })}
onResizeStop={(e, dir, ref, delta, pos) =>
onUpdate({ x: pos.x, y: pos.y, width: ref.offsetWidth, height: ref.offsetHeight })
}

<div className="widget-preview">Widget</div>
`

Question

Is there an official or recommended way to use react-rnd inside a scaled parent container without the position drifting?

Is this behavior expected due to DOM measurements under CSS transforms, or is it a bug?

If needed, I can provide:

A minimal reproducible CodeSandbox

A video example

My current overlay editor structure

Thank you very much for your time!

Activity

  1. chris-maheu commented on Mar 10, 2026

    @chris-maheu

    I'm experiencing a similar issue, hoping for a solution soon!

  2. KevinArce98 commented on Sep 7, 2026

    @KevinArce98

    This is a structural problem rather than a bug in a specific version. react-rnd applies the pointer delta in screen pixels to an element that lives in a scaled coordinate space, so every pixel of drag moves the element by 1 / scale too much or too little, and the error accumulates over the drag.

    The workaround with scale prop helps for a single uniform scale but breaks again with nested transforms or CSS zoom.

    If you need it to work in that setup, I built frameable around exactly this case. It converts pointer positions through a Surface matrix before computing anything, and computes deltas from the initial pointer position rather than accumulating them, so there is no drift. The demo has a toggle that applies zoom: 0.6 to the parent plus a 2x viewport zoom while you drag and resize: https://kevinarce98.github.io/frameable/

    Migration from Rnd is mostly moving the position and size into state, which you likely already do to persist them. Details: https://github.com/KevinArce98/frameable#readme

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions