204

Is there a way to prevent the user from seeing a ghost of the image they are trying to drag (not concern about security of the images, but the experience).

I've tried this which fixes the problem with the blue selection on text and images but not the ghost image:

img {
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -o-user-select: none;
  user-select: none;
}

(I also tried nesting the image inside a div with the same rules applied to the div). Thanks

BoltClock
  • 665,005
  • 155
  • 1,345
  • 1,328
user885355
  • 2,969
  • 4
  • 17
  • 10

19 Answers19

252

You can set the draggable attribute to false in either the markup or JavaScript code.

// As a jQuery method: $('#myImage').attr('draggable', false);
document.getElementById('myImage').setAttribute('draggable', false);
<img id="myImage" src="http://placehold.it/150x150">
BoltClock
  • 665,005
  • 155
  • 1,345
  • 1,328
  • 106
    Why add it with JavaScript??? `` – Greg Aug 08 '13 at 11:45
  • 38
    @Greg: Why are you asking me? It's the OP who wanted a JavaScript solution. Plus I did say "in either the markup or JavaScript code" anyway, so it's not like you *couldn't* do it in the markup if you had the option of editing your markup. – BoltClock Aug 08 '13 at 11:49
  • 21
    Doesn't work in FF in combination with `-moz-user-select: none`. Possible solution: Add `pointer-events: none`. – Cedric Reichenbach Apr 05 '14 at 14:10
  • 9
    Maybe I have misinterpreted the question but isn't the OP asking how they can retain drag & drop but just hide the ghosted image? Setting `draggable` to `false` will completely disable drag & drop. – James Jun 24 '14 at 10:21
  • 2
    @James: It's not very clear from the question, to be honest. I'm mostly answering under the assumption that the ghost image is visual indicator for drag-and-drop (which it is), and that most people who want to hide the ghost image generally don't care if drag-and-drop is disabled altogether. – BoltClock Jun 26 '14 at 01:28
  • @BoltClock the reason for my comment was because I wanted to do exactly that; retain drag & drop but avoid generating the image. I consequently had to eventually give up on the native drag & drop but I still feel this type of functionality would be useful. – James Jun 26 '14 at 10:13
  • 1
    Note that `pointer-events: none` will disable all pointer events, including any desired clicks. Which wouldn't be good for something like the `map` tag, or anything else you'd want to click but not drag. – Beejor Feb 02 '15 at 20:49
  • Note that the `draggable` attribute requires HTML5 and at least IE 9, Safari 6, or Opera 12. – Beejor Dec 03 '16 at 02:45
  • this doesn't work if the parent has a `dragover` or `drop` event associated with it. is there another way? – oldboy May 24 '17 at 05:23
  • @Anthony: Not that I know of - I wrote this answer with the assumption that the author does not intend for the image to be dragged at all. – BoltClock May 24 '17 at 05:41
  • @BoltClock yes, that's exactly what i'm talking about--not allowing something to be dragged at all. none of these ways work for me. [here is the question i just posted.](https://stackoverflow.com/questions/44149403/prevent-ghost-image-on-dragging-non-draggable-elements?noredirect=1#comment75316600_44149403) – oldboy May 24 '17 at 05:54
  • Hi everyone, I'm facing this issue in firefox 59.0.2 (64-bit) but not in any other browsers. The sample gets dragged in firefox. Any help? – kingshuk basak Apr 26 '18 at 08:22
  • 1
    You actually need to do `element.setAttribute("draggable","false");`. Tested in Firefox 70 and directly setting `element.draggable = "false"` will not always work. E.g., when DOM element has not yet been appended to page – Azmisov Oct 25 '19 at 16:23
  • @Azmisov: Thanks for pointing this out. This limitation does not appear to be mentioned in the spec (alternatively, it could be an issue with Firefox). In hindsight, I don't know why I didn't just go with that as a counterpart to jQuery's .attr()... – BoltClock Oct 27 '19 at 13:27
  • @James You could set the drag image to a minimum or transparent image. `ondragstart` set `event.dataTransfer.setDragImage(img, 0, 0);` The image could for example be https://stackoverflow.com/a/13139830/3342816 – user3342816 Nov 04 '21 at 19:34
124

I think you can change your

img {
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -o-user-select: none;
  user-select: none;
}

into a

img {
  -webkit-user-drag: none;
  -khtml-user-drag: none;
  -moz-user-drag: none;
  -o-user-drag: none;
  user-drag: none;
}
chpio
  • 687
  • 3
  • 15
Max
  • 1,273
  • 1
  • 8
  • 2
  • 4
    @victorsosa True, but a de-facto standard is still a standard, W3C or not. That is, if every browser supports it, it's good to go. Remember that a lot of W3C stuff started out as proprietary, like AJAX. – Beejor Dec 03 '16 at 02:49
  • 6
    This solution does not work in IE11 and Firefox 57.0. – Tudor Ciotlos Jan 17 '18 at 13:40
48

Try it:

img {
  pointer-events: none;
}

and try to avoid

* {
  pointer-events: none;
}
chpio
  • 687
  • 3
  • 15
Erik Rybalkin
  • 919
  • 11
  • 20
  • 27
    This is a poor solution, as it removes all ability to interact with the element. OP is only asking to disable the "drag" functionality of an element, not to entirely disable any and all pointer-based interaction with the element. – Chad Dec 28 '18 at 20:42
  • 6
    @Chad that's true but it's possible to wrap the image and add the event listener to wrapper while the image has no ghost image anymore. – Vincent Hoch-Drei Feb 21 '19 at 10:32
23

This will disable dragging for an image in all browsers, while preserving other events such as click and hover. Works as long as any of HTML5, JS, or CSS are available.

<img draggable="false" onmousedown="return false" style="user-drag: none" />

If you're confident the user will have JS, you only need to use the JS attribute, etc. For more flexibility, look into ondragstart, onselectstart, and some WebKit tap/touch CSS.

Beejor
  • 7,402
  • 39
  • 31
  • You might want to do (this.onclick || this.click)() instead.. if onclick can be undefined according to this logic? – Van Nguyen Oct 17 '16 at 11:47
  • @Kaizoku Thanks, I hadn't considered that! Updated my answer based on your suggestion. – Beejor Nov 04 '16 at 04:14
  • This doesn't seem to work in FireFox because, strictly speaking, do not even have onclick or click events. Anyways, I just used the onmouseup portion and let the parent DIV handle the onclick and it works. – Nelson Nov 28 '16 at 09:00
  • @Nelson Thanks for letting me know. It seems the onmouseup wasn't needed anyway since onclick fires regardless of the return value from any onmousedown/up handler. I decided to revise my answer for simplicity. The new one-liner should work fine; just tested in FF, Safari, Chrome, IE8/10. – Beejor Dec 03 '16 at 02:39
  • I'm on Firefox 62 and `onmousedown="return false"` is sufficient. It is also needed to avoid the user selecting the image while dragging on it, which then would allow them to drag the selection. – loxaxs Oct 06 '18 at 19:38
22

You can use a CSS property to disable images in webkit browsers.

img{-webkit-user-drag: none;}
mins
  • 5,216
  • 10
  • 48
  • 66
Ashwani
  • 273
  • 2
  • 5
  • 4
    This also works with `-ms-user-drag`, `-moz-user-drag`, and `user-drag`. A great CSS-only solution! – Beejor Dec 03 '16 at 02:41
14

Very simple don't make it complicated with lots of logic use simple attribute draggable and make it false

<img draggable="false" src="img/magician.jpg" alt="" />
MD SHAYON
  • 7,911
  • 47
  • 35
11

The be-all-end-all, for no selecting or dragging, with all browser prefixes:

-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
user-select: none;

-webkit-user-drag: none;
-khtml-user-drag: none;
-moz-user-drag: none;
-o-user-drag: none;
-ms-user-drag: none;
user-drag: none;

You can also set the draggable attribute to false. You can do this with inline HTML: draggable="false", with Javascript: elm.draggable = false, or with jQuery: elm.attr('draggable', false).

You can also handle the onmousedown function to return false. You can do this with inline HTML: onmousedown="return false", with Javascript: elm.onmousedown=()=>return false;, or with jQuery: elm.mousedown(()=>return false)

Justin
  • 778
  • 7
  • 23
9
<img src="myimage.jpg" ondragstart="return false;" />
lubosdz
  • 3,904
  • 2
  • 26
  • 39
9

Handle the dragstart event and return false.

SLaks
  • 837,282
  • 173
  • 1,862
  • 1,933
4

You can assign an alternate ghost image if you really need to use drag events and can't set draggable=false. So just assign a blank png like so:

    $('#img').bind({
        dragstart: function(e) {
            var dragIcon = document.createElement('img');
            dragIcon.src = 'blank.png';
            dragIcon.width = 100;
            e.dataTransfer.setDragImage(dragIcon, -10, -10);
        }
    });
louisinhongkong
  • 531
  • 5
  • 13
4

Place the image as a background of an empty div, or under a transparent element. When the user clicks on the image to drag, they are clicking on a div.

See http://www.flickr.com/photos/thefella/5878724253/?f=hp

<div id="photo-drag-proxy"></div>
Michael Jasper
  • 7,862
  • 4
  • 40
  • 58
3

For Firefox you need to go a little deeper with this:

var imgs = document.getElementsByTagName('img');

    // loop through fetched images
    for (i = 0; i < imgs.length; i++) {
        // and define onmousedown event handler
        imgs[i].onmousedown = disableDragging;
    }

function disableDragging(e) {
        e.preventDefault();
    }

Enjoy.

dijipiji
  • 2,897
  • 1
  • 26
  • 21
1

I found that for IE, you must add the draggable="false" attribute to images and anchors to prevent dragging. the CSS options work for all other browsers. I did this in jQuery:

$("a").attr('draggable', false); 
$("img").attr('draggable', false);
Derek Wade
  • 647
  • 7
  • 11
1

There is a much easier solution here than adding empty event listeners. Just set pointer-events: noneto your image. If you still need it to be clickable, add a container around it which triggers the event.

Micros
  • 5,538
  • 2
  • 25
  • 33
1

When Firefox does not appreciate your draggable attribute (when set to false) or none of your user-drag CSS rules in your link/anchor or image element:

Firefox user-drag CSS rules rejected

And you want to keep pointer-events as they are, you may use the big guns for that ghostly "translucent image generated from the drag target (the element the dragstart event is fired at)" as described in MDN setDragImage. Simply use:

if (/(firefox)/i.test(navigator.userAgent)) {
  document.querySelector('.my-non-draggable').addEventListener('dragstart',
    e => e.preventDefault()
  );
  // or jQuery: $('.my-non-draggable').on('dragstart', e => e.preventDefault());
}
CPHPython
  • 9,522
  • 4
  • 50
  • 66
0

Tested on Firefox: removing and putting back the image works! And it's transparent at the execution, too. For instance,

$('.imageContainerClass').mousedown(function() {
    var id = $(this).attr('id');
    $('#'+id).remove();
    $('#'+id).append('Image tag code');
});

EDIT: This works only on IE and on Firefox, strangely. I also added draggable = false on each image. Still a ghost with Chrome and Safari.

EDIT 2: The background-image solution is genuinely the best one. The only subtlety is that the background-size property has to be redefined every time the background-image is changed! Or so, that's what it looked like from my side. Better still, I had an issue with normal img tags under IE, where IE failed to resize the images. Now, the images have the correct dimensions. Simple:

$(id).css( 'background-image', url('blah.png') );
$(id).css( 'background-size', '40px');

Also, perhaps consider those:

background-Repeat:no-repeat;
background-Position: center center;
Tama Yoshi
  • 193
  • 1
  • 15
0

You can set the image that is shown when an item is dragged. Tested with Chrome.

setDragImage

use

onclick = myFunction();
myFunction(e) {
    e.dataTransfer.setDragImage(someImage, xOffset, yOffset);
}

Alternatively, as already mentioned in the answers, you can set draggable="false" on the HTML element, if not being able to drag the element at all is no issue.

Colin Cline
  • 1,251
  • 1
  • 12
  • 24
0

You can use "Empty Img Element".
Empty Img Element - document.createElement("img")

[HTML Code]
<div id="hello" draggable="true">Drag!!!</div>
[JavaScript Code]
var block = document.querySelector('#hello');
block.addEventListener('dragstart', function(e){
    var img = document.createElement("img");
    e.dataTransfer.setDragImage(img, 0, 0);
})
-2

This work for me, i use some lightbox scripts

.nodragglement {
    transform: translate(0px, 0px)!important;
}