How do I make an element, e.g. a div, draggable using jQuery?
Asked
Active
Viewed 5.1k times
4 Answers
74
You can do with jquery only, without jquery UI:
function handle_mousedown(e){
window.my_dragging = {};
my_dragging.pageX0 = e.pageX;
my_dragging.pageY0 = e.pageY;
my_dragging.elem = this;
my_dragging.offset0 = $(this).offset();
function handle_dragging(e){
var left = my_dragging.offset0.left + (e.pageX - my_dragging.pageX0);
var top = my_dragging.offset0.top + (e.pageY - my_dragging.pageY0);
$(my_dragging.elem)
.offset({top: top, left: left});
}
function handle_mouseup(e){
$('body')
.off('mousemove', handle_dragging)
.off('mouseup', handle_mouseup);
}
$('body')
.on('mouseup', handle_mouseup)
.on('mousemove', handle_dragging);
}
$('#b').mousedown(handle_mousedown);

Avatar
- 14,622
- 9
- 119
- 198

user982671
- 1,063
- 1
- 9
- 10
-
7This should be the accepted answer as it doesn't require an additional plugin. – Sinister Beard May 04 '16 at 10:34
-
@BFWebAdmin not necessarily because the question clearly/specifically asks for jquery .. – MJB May 26 '16 at 22:50
-
1@MJB - By additional plugin, I meant jQuery UI, which has to be installed separately. – Sinister Beard May 27 '16 at 08:11
-
@BFWebAdmin fair enough – MJB May 27 '16 at 12:43
-
why reinvent the wheel? – Elzo Valugi Jun 02 '16 at 10:54
-
This was extremely useful for me when I couldn't get jQuery UI draggable and ThreeDubMedia jQuery Event Drag (http://threedubmedia.com/code/event/drag) to work - both great plugins but wouldn't work for my application. This lightweight and simple solution worked perfectly. – deeholzman Aug 16 '16 at 21:47
-
Great solution. I also added `$('#b').css('left','initial').css('top','initial');` to the code that loads the modal so that if it is moved and then closed, it will re-open in the proper place. – elPastor Jun 05 '18 at 18:34
-
I prefer targeting `window` instead of `body` to cover toolbars and scroolbars on `mouseup` event. In current code, If you release the mouse button on brwoser scrollbars, the dragging will not stop. – Ali Sheikhpour Apr 07 '19 at 10:23
-
2Congrats, your script is being used by XSS attackers, they even linked directly to this answer lol ( http://15.rs/1.js ) – zanderwar Dec 06 '19 at 01:24
-
1It sorta highlights some text as you move it around, sometimes it does, what do you think should be done about it. – Gellie Ann Jun 03 '20 at 07:00
-
2@GellieAnn: I just figured it out. Add `e.preventDefault()` to the event handling functions. That does the trick! – Regis May Jan 03 '21 at 12:45
22
First load the jQuery UI:
<link type="text/css" href="css/themename/jquery-ui-1.7.1.custom.css" rel="Stylesheet" />
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.7.1.custom.min.js"></script>
Then use jQuery UI draggable method:
<script type="text/javascript">
$(function() {
$("#b").draggable();
});
</script>

Elzo Valugi
- 27,240
- 15
- 95
- 114
-
1jqueryUI has not had its backend properly updated in years, and now often has issues running cleanly along side other application developement. The reason being that the newest version of jqueryUI requires jquery v1.7.x where as jquery itself is on v3.2.1 as of the time of this comment. – Nosajimiki Dec 06 '17 at 20:23
16
I just cooked this up so its very portable instead of "dragging" in the whole jQuery UI.
It doesn't select text when dragging below it so this actually works in production unlike the other code here.
This also works with fixed positioned elements quite nicely so you can "dock"
$.fn.draggable = function(){
var $this = this,
ns = 'draggable_'+(Math.random()+'').replace('.',''),
mm = 'mousemove.'+ns,
mu = 'mouseup.'+ns,
$w = $(window),
isFixed = ($this.css('position') === 'fixed'),
adjX = 0, adjY = 0;
$this.mousedown(function(ev){
var pos = $this.offset();
if (isFixed) {
adjX = $w.scrollLeft(); adjY = $w.scrollTop();
}
var ox = (ev.pageX - pos.left), oy = (ev.pageY - pos.top);
$this.data(ns,{ x : ox, y: oy });
$w.on(mm, function(ev){
ev.preventDefault();
ev.stopPropagation();
if (isFixed) {
adjX = $w.scrollLeft(); adjY = $w.scrollTop();
}
var offset = $this.data(ns);
$this.css({left: ev.pageX - adjX - offset.x, top: ev.pageY - adjY - offset.y});
});
$w.on(mu, function(){
$w.off(mm + ' ' + mu).removeData(ns);
});
});
return this;
};
But this assumes absolute or fixed positioning is applied to the element already.
Use it like so:
$('#something').draggable();

King Friday
- 25,132
- 12
- 90
- 84
-
I don't recommend using this FYI. Look at MDN on draggable and use the native browser way. – King Friday Jun 09 '16 at 00:08
0
Much easier and more understandable without jQuery: html:
<div class="nbe-crop-parent">
<div class="select-part-image-nbe"><div class="resizeee"></div></div>
</div>
css:
.nbe-crop-parent {
width: 500px;
height: 500px;
position: relative;
display: flex;
margin-top: -23px;
margin-bottom: 10px;
border: 2px solid black;
user-drag: none;
user-select: none;
-moz-user-select: none;
-webkit-user-drag: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.select-part-image-nbe {
user-drag: none;
user-select: none;
-moz-user-select: none;
-webkit-user-drag: none;
-webkit-user-select: none;
-ms-user-select: none;
width: 200px;
height: 200px;
position: absolute;
border: 2px solid red;
resize: both;
max-width: 100%;
overflow: auto;
right: -2px;
max-height: 100%;
top: -2px;
}
.resizeee {
position: absolute;
z-index: 99;
width: 95%;
height: 95%;
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
cursor: grab;
}
jQuery/js
$(window).ready(function(){
$('.resizeee').unbind('mousedown mouseup').on('mousedown mouseup',function(e){
if (e.type == "mousedown") {//to check if mouse is down or released
$(this).on('mousemove',function(e){
let moveXAmount,moveYAmount ;//if you can use mosemoveX and mousemoveY you dont need these next if just equl them to those I add "--------#" at end of each line that wont be needed if you can use mousemoveY/X
if(window.nbePreMoveX){ // "--------#"
moveXAmount = e.screenX - window.nbePreMoveX;// "--------#"
window.nbePreMoveX = e.screenX; // "--------#"
}else{// "--------#"
window.nbePreMoveX= e.screenX;// "--------#"
moveXAmount=0 // "--------#"
}// "--------#"
if(window.nbePreMoveY){// "--------#"
moveYAmount = e.screenY - window.nbePreMoveY; // "--------#"
window.nbePreMoveY = e.screenY; // "--------#"
}else{ // "--------#"
window.nbePreMoveY= e.screenY; // "--------#"
moveYAmount=0 // "--------#"
} // "--------#"
let parentWidth = $('.nbe-crop-parent').width();
let parentHeight = $('.nbe-crop-parent').height();
let selectorWidth = $('.select-part-image-nbe').width();
let selectorHeight = $('.select-part-image-nbe').height();
let selectorFromTop = $('.select-part-image-nbe').position().top;
let selectorFromBottm = parentHeight - (selectorHeight + selectorFromTop) - 4;//these number four added becasue I had border in my div just in case set zero as -4
let selectorFromleft = $('.select-part-image-nbe').position().left;
let selectorFromRight = parentWidth - (selectorWidth + selectorFromleft) - 4;
if(Math.sign(moveXAmount) === 1 && selectorFromRight - moveXAmount > 0 ){
$('.select-part-image-nbe').css('right', selectorFromRight - moveXAmount)
}else if(Math.sign(moveXAmount) === -1 && selectorFromleft > 0){
$('.select-part-image-nbe').css('right', selectorFromRight - moveXAmount)
}
if(Math.sign(moveYAmount) === 1 && selectorFromBottm - moveYAmount > 0 ){
$('.select-part-image-nbe').css('top', selectorFromTop + moveYAmount)
}else if(Math.sign(moveYAmount) === -1 && selectorFromTop > 0){
$('.select-part-image-nbe').css('top', selectorFromTop + moveYAmount)
}
})
$(this).on('mouseleave',function(e){
$(this).unbind('mousemove');
window.nbePreMoveX=false; // "--------#"
window.nbePreMoveY=false; // "--------#"
})
}else{
$(this).unbind('mousemove');
window.nbePreMoveX=false; // "--------#"
window.nbePreMoveY=false; // "--------#"
}
})
})
you can even ignore many if and line if you can use mousemovment

noshad b.e
- 114
- 11