79640619

Date: 2025-05-27 13:54:26
Score: 1
Natty:
Report link

Answering my own question. One workaround is to clone and temporarily insert the dragged element into the DOM, and then set that as the drag image on the event data transfer object. This also has the benefit of the drag image being positioned correctly when specifying the X and Y coordinates, unlike the natively inserted drag image, which doesn't take the transform of the ancestor into account.

Here's an updated Codepen example. https://codepen.io/Veikko-Lehmuskorpi/pen/oggKRZv

const source = document.querySelector(".item");
let ghostEl;

source.addEventListener("dragstart", (event) => {
  ghostEl = event.target.cloneNode(true);
  ghostEl.classList.add("ghost");
  document.body.appendChild(ghostEl);
  event.dataTransfer.setDragImage(ghostEl, event.offsetX, event.offsetY);
});

source.addEventListener("dragend", () => {
  ghostEl.remove();
});
body {
  margin: 0;
}

.container {
  width: 100vw;
  height: 100vh;
  background: #ccc;

  /* This breaks dragging the child item on Safari, unless a custom drag image is set */
  transform: scale(0.5);
}

.item {
  background: #ddd;
  width: 300px;
  height: 150px;
  font-size: 72px;
}

.ghost {
  position: absolute;
  top: -99999px;
  left: -99999px;
}
<div class="container">
  <div class="item" draggable="true">
    draggable
  </div>
</div>

Reasons:
  • Contains signature (1):
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: Veikko