jQuery draggable moves when dropped

I have set up a simple drag and drop interface which implements the clone functionality. The issue I have is that when the element is dragged to the main canvas and then dropped, it suddenly shifts to the right, rather than dropping exactly where I drag it.

Here is the javascript:

$(function() {
  var x = null;

    helper: 'clone',
    cursor: 'move',
    snap: '.snap-target'

    drop: function(e, ui) {
      if ($(ui.draggable)[0].id != "") {
        x = ui.helper.clone();
          helper: 'original',
          containment: '#canvas',
          snap: '.snap-target'

I have created a jsfiddle:


If you try and drag the blue box into the main canvas then release the mouse you will see how the box “pops” to the right slightly. When you move the box within the canvas, it works fine. On the fiddle it’s not as bad as when it’s full width on a browser, I think it’s relative to the total width of the viewport.

If anyone knows why this may be happening I would appreciate it :)


The reason this is occuring is because the draggable element is absolutely positioned relative to the viewport while it is being dragged. Once the element is appended, the positioning is relative to the #canvas element (because of position: relative), which is why the element moves when you drop it.

As the other answer suggests, you could remove position: relative from the element, however, that probably won’t work in all cases. I’d suggest taking the positioning of the element into account before appending the element.

Updated Example

For instance, you could subtract the offset top/left positioning, as well as the width of the border. In doing so, the #canvas element can still be relatively positioned.

var canvasOffset = {
  'top': parseInt($(this).offset().top, 10) + parseInt($(this).css('border-top-width'), 10),
  'left': parseInt($(this).offset().left, 10) + parseInt($(this).css('border-left-width'), 10)

  "top": parseInt($draggble.css('top'), 10) - canvasOffset.top + 'px',
  "left": parseInt($draggble.css('left'), 10) - canvasOffset.left + 'px'