HTML5 Drag and Drop - No transparency?

Problem

When I drag and drop an element on my page the element becomes "ghosted". Basically it gets some transparency value.

Is there some way to make it opacity: 1;?

Problem courtesy of: Ndushi

Solution

It looks like it can't be done. The dragged element is put into container that has it's own, lower than 1, opacity. This means that while you can lower the opacity of the dragged element you can't get it higher than the opacity of the encapsulating element.

It might be possible to override default browser settings for such element, but since nothing is added to DOM during the drag it would be very tricky at best.

Solution courtesy of: c2h5oh

Discussion

As others have suggested, you will need some sort of mechanism that will:

  1. Hide the element that is being dragged.
  2. Make a clone of the element that is being dragged.
  3. Put the clone in place of the element that is being dragged.
  4. Listen to the drag event to position the clone element.

In practise, looks like this:

function Drag (subject) {
    var dative = this,
        handle,
        dragClickOffsetX,
        dragClickOffsetY,
        lastDragX,
        lastDragY;

    subject.draggable = true;

    dative.styleHandle(subject);

    subject.addEventListener('dragstart', function (e) {    
        handle = dative.makeHandle(subject);

        dragClickOffsetX = e.layerX;
        dragClickOffsetY = e.layerY;

        this.style.opacity = 0;
    });

    subject.addEventListener('drag', function (e) {
        var useX = e.x,
            useY = e.y;

        // Odd glitch
        if (useX === 0 && useY === 0) {
            useX = lastDragX;
            useY = lastDragY;
        }

        if (useX === lastDragX && useY === lastDragY) {
            return;
        }

        dative.translate(useX - dragClickOffsetX, useY - dragClickOffsetY, handle, subject);

        lastDragX = useX;
        lastDragY = useY;
    });

    subject.addEventListener('dragend', function (e) {
        this.style.opacity = 1;

        handle.parentNode.removeChild(handle);
    });
};

/**
 * Prevent the text contents of the handle element from being selected.
 */
Drag.prototype.styleHandle = function (node) {
    node.style['userSelect'] = 'none';
};

/**
 * @param {HTMLElement} subject
 * @return {HTMLElement}
 */
Drag.prototype.makeHandle = function (subject) {
    return this.makeClone(subject);
};

/**
 * Clone node.
 * 
 * @param {HTMLElement} node
 * @return {HTMLElement}
 */
Drag.prototype.makeClone = function (node) {
    var clone;

    clone = node.cloneNode(true);

    this.styleClone(clone, node.offsetWidth, node.offsetHeight);

    node.parentNode.insertBefore(clone, node);

    return clone;
};

/**
 * Make clone width and height static.
 * Take clone out of the element flow.
 *
 * @param {HTMLElement} node
 * @param {Number} width
 * @param {Nubmer} height
 */
Drag.prototype.styleClone = function (node, width, height) {
    node.style.position = 'fixed';
    node.style.zIndex = 9999;
    node.style.width = width + 'px';
    node.style.height = height + 'px';
    node.style.left = '-9999px';

    node.style.margin = 0;
    node.style.padding = 0;
};

/**
 * Used to position the handle element.
 * 
 * @param {Number} x
 * @param {Number} y
 * @param {HTMLElement} handle
 * @parma {HTMLElement} subject
 */
Drag.prototype.translate = function (x, y, handle, subject) {
    handle.style.left = x + 'px';
    handle.style.top = y + 'px';
};

Start with attaching an element:

new Drag(document.querySelector('.element'));

And you have a working drag and drop with full control over the looks of the draggable element. In the above example, I clone the original element to use it as the handle. You can extend the Drag function to customise the handle (e.g. use image to represent the draggable element).

Before you get too excited, there are couple of things to consider:

Update:

I have written a library for touch enabled implementation of WHATWG drag and drop mechanism, https://github.com/gajus/pan.

Discussion courtesy of: Gajus

I think the transparency doesn't come from the web contents but from the browser and OS. If you want to change the opacity, you must to tweak or hack the browser and OS

Discussion courtesy of: micgdev

If you are not dragging and dropping elements from outside of the web page (from the operating system) then you could solve this problem easily by implementing your own drag and drop. There are numerous examples of pure javascript drag and drop which will function perfectly in an HTML5 environment and would be completely customizable by you.

answer: (use the old way)

Discussion courtesy of: Joshua

If you are using JavaScript then in the function which handles the dragStart event include set the style opacity to 1 example:

function dragStartHandler(e) {
   this.style.opacity = '1.0';
}
Discussion courtesy of: dhuckle3

Please see this working fiddle

I have a solution for making an opaque image in the place of ghost and it works fine in chrome.But its not working in FF.I need some body to help me to make it work in Firefox and other browsers. steps 1.We will make our own ghost image and will set it as the drag image.

document.addEventListener("dragstart", function(e) {
var img = document.createElement("img");
img.src = "img/hackergotchi-simpler.png";
e.dataTransfer.setDragImage(img, 5000, 5000);//5000 will be out of the window
}, false);

2.We will clone the image and append it to DOM ondrag

var crt,dragX,dragY;
function drag(ev) {
    crt = ev.target.cloneNode(true);
    crt.style.position = "absolute"; 
    document.body.appendChild(crt);
    ev.dataTransfer.setData("text", ev.target.id);
}

3.Then we will make the clone to move with cursor

    document.addEventListener("dragover", function(ev){
ev = ev || window.event;
dragX = ev.pageX; dragY = ev.pageY;
crt.style.left=dragX+"px";crt.style.top=  dragY+"px";
console.log("X: "+dragX+" Y: "+dragY);
}, false);

4.At Last we will make the clone visibility gone

   document.addEventListener("dragend", function( event ) {crt.style.display='none';});
Discussion courtesy of: Ninjaneer

Suggestion, do the following, now for this I m using jQuery, try it, before saying something wont work, we are not here to give answers, but here to point you in the right direction.

function dragStartHandler(e) { 
   $("span.{CLASS}")addClass('overdrag'); 
} 

then you need to come up with away to tell that it has stoped draging and dropped into position, and then to RemoveClass('overdrag');

This is not hard to do, so I think you should be able to do it. I want to thank @DonaldHuckle as this is really his solution not mine.

Discussion courtesy of: RussellHarrower

altough this is propably not the real solution of the core problem, I have an idea what might work, at least I tested this in one of my GWT project some time ago and it worked, so I guess it might work in native JS as well altough I have no code example:

  1. Instead of using the dragging function, create a new element which equals the element that should be dragget at the original position of the element to be dragged. The original Element to be dragged should be made invisible now. Implement a logic that restores the orignal element and removes the clone as soon as the mouse isn't pressed anymore.

  2. Make the clone Element stick to the mouse's position. The event that removes the clone has also to check if the mouse is released while the element to drag is positioned over an area where the original ement could be dragged to.

  3. If true, remove the clone and move the original element to the target container.

There is definitely a lot of adjustment work to do in CSS and JS as well, but It might be a trick to overwhelm the JS standard.

Discussion courtesy of: Corsair

as already mentioned, this is handled by the browser -> you cannot change this behavior, but if you really need this effect try to look for mouse move when mouse is down (short: dragging), check what element is selected and create a copy on the fly that follows your mouse cursor. looks like an ideal job for jQuery ;)

but if you don't need it desperately I wouldn't try to change the browsers' default values, as people are used to it and may be confused if something behaves in another (unknown) way

Discussion courtesy of: Peter

This recipe can be found in it's original form on Stack Over Flow.