HTML5 Drag and Drop - No transparency?

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:

  • WHATWG Drag and Drop does not work with mobile, HTML5 Drag & Drop for Mobile
  • There is no way to capture the "handle release" event, See the link for the solution: How to get mouseup event after native drag event?.

Update:

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


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)


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.