1. 6.9 Drag and drop
      1. 6.9.1 Introduction
      2. 6.9.2 The drag data store
      3. 6.9.3 The DataTransfer interface
        1. 6.9.3.1 The DataTransferItemList interface
        2. 6.9.3.2 The DataTransferItem interface
      4. 6.9.4 The DragEvent interface
      5. 6.9.5 Events summary
      6. 6.9.6 The draggable attribute

6.9 Drag and drop

HTML_Drag_and_Drop_API

Support in all current engines.

Firefox3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)18Internet Explorer5.5+
Firefox Android4+Safari iOS2+Chrome Android18+WebView Android4.4+Samsung Internet1.5+Opera Android14+
caniuse.com table

This section defines an event-based drag-and-drop mechanism.

This specification does not define exactly what a drag-and-drop operation actually is.

On a visual medium with a pointing device, a drag operation could be the default action of a mousedown event that is followed by a series of mousemove events, and the drop could be triggered by the mouse being released.

When using an input modality other than a pointing device, users would probably have to explicitly indicate their intention to perform a drag-and-drop operation, stating what they wish to drag and where they wish to drop it, respectively.

6.9.1 Introduction

To make an element draggable, give the element a draggable attribute, and set an event listener for dragstart that stores the data being dragged.

The event handler typically needs to check that it's not a text selection that is being dragged, and then needs to store data into the DataTransfer object and set the allowed effects (copy, move, link, or some combination).

For example:

<p>What fruits do you like?</p>
<ol ondragstart="dragStartHandler(event)">
 <li draggable="true" data-value="fruit-apple">Apples</li>
 <li draggable="true" data-value="fruit-orange">Oranges</li>
 <li draggable="true" data-value="fruit-pear">Pears</li>
</ol>
<script>
  var internalDNDType = 'text/x-example'; // set this to something specific to your site
  function dragStartHandler(event) {
    if (event.target instanceof HTMLLIElement) {
      // use the element's data-value="" attribute as the value to be moving:
      event.dataTransfer.setData(internalDNDType, event.target.dataset.value);
      event.dataTransfer.effectAllowed = 'move'; // only allow moves
    } else {
      event.preventDefault(); // don't allow selection to be dragged
    }
  }
</script>

To accept a drop, the drop target has to listen to the following events:

  1. The dragenter event handler reports whether or not the drop target is potentially willing to accept the drop, by canceling the event.
  2. The dragover event handler specifies what feedback will be shown to the user, by setting the dropEffect attribute of the DataTransfer associated with the event. This event also needs to be canceled.
  3. The drop event handler has a final chance to accept or reject the drop. If the drop is accepted, the event handler must perform the drop operation on the target. This event needs to be canceled, so that the dropEffect attribute's value can be used by the source. Otherwise, the drop operation is rejected.

For example:

<p>Drop your favorite fruits below:</p>
<ol ondragenter="dragEnterHandler(event)" ondragover="dragOverHandler(event)"
    ondrop="dropHandler(event)">
</ol>
<script>
  var internalDNDType = 'text/x-example'; // set this to something specific to your site
  function dragEnterHandler(event) {
    var items = event.dataTransfer.items;
    for (var i = 0; i < items.length; ++i) {
      var item = items[i];
      if (item.kind == 'string' && item.type == internalDNDType) {
        event.preventDefault();
        return;
      }
    }
  }
  function dragOverHandler(event) {
    event.dataTransfer.dropEffect = 'move';
    event.preventDefault();
  }
  function dropHandler(event) {
    var li = document.createElement('li');
    var data = event.dataTransfer.getData(internalDNDType);
    if (data == 'fruit-apple') {
      li.textContent = 'Apples';
    } else if (data == 'fruit-orange') {
      li.textContent = 'Oranges';
    } else if (data == 'fruit-pear') {
      li.textContent = 'Pears';
    } else {
      li.textContent = 'Unknown Fruit';
    }
    event.target.appendChild(li);
  }
</script>

To remove the original element (the one that was dragged) from the display, the dragend event can be used.

For our example here, that means updating the original markup to handle that event:

<p>What fruits do you like?</p>
<ol ondragstart="dragStartHandler(event)" ondragend="dragEndHandler(event)">
 ...as before...
</ol>
<script>
  function dragStartHandler(event) {
    // ...as before...
  }
  function dragEndHandler(event) {
    if (event.dataTransfer.dropEffect == 'move') {
      // remove the dragged element
      event.target.parentNode.removeChild(event.target);
    }
  }
</script>

6.9.2 The drag data store

The data that underlies a drag-and-drop operation, known as the drag data store, consists of the following information:

When a drag data store is created, it must be initialized such that its drag data store item list is empty, it has no drag data store default feedback, it has no drag data store bitmap and drag data store hot spot coordinate, its drag data store mode is protected mode, and its drag data store allowed effects state is the string "uninitialized".

6.9.3 The DataTransfer interface

DataTransfer objects are used to expose the drag data store that underlies a drag-and-drop operation.

dataTransfer = new DataTransfer()

DataTransfer/DataTransfer

Support in one engine only.

Firefox?SafariNoChrome60+
Opera47+Edge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android?Safari iOSNoChrome Android60+WebView Android60+Samsung Internet8.0+Opera Android44+

Creates a new DataTransfer object with an empty drag data store.

dataTransfer . dropEffect [ = value ]

DataTransfer/dropEffect

Support in all current engines.

FirefoxYesSafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet Explorer?
Firefox AndroidYesSafari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Returns the kind of operation that is currently selected. If the kind of operation isn't one of those that is allowed by the effectAllowed attribute, then the operation will fail.

Can be set, to change the selected operation.

The possible values are "none", "copy", "link", and "move".

dataTransfer . effectAllowed [ = value ]

DataTransfer/effectAllowed

Support in all current engines.

FirefoxYesSafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet Explorer?
Firefox AndroidYesSafari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Returns the kinds of operations that are to be allowed.

Can be set (during the dragstart event), to change the allowed operations.

The possible values are "none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", and "uninitialized",

dataTransfer . items

DataTransfer/items

Firefox50+SafariNoChrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android52+Safari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Returns a DataTransferItemList object, with the drag data.

dataTransfer . setDragImage(element, x, y)

DataTransfer/setDragImage

Support in all current engines.

FirefoxYesSafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)18Internet Explorer?
Firefox AndroidYesSafari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Uses the given element to update the drag feedback, replacing any previously specified feedback.

dataTransfer . types

DataTransfer/types

Support in all current engines.

FirefoxYesSafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidYesSafari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Returns a frozen array listing the formats that were set in the dragstart event. In addition, if any files are being dragged, then one of the types will be the string "Files".

data = dataTransfer . getData(format)

DataTransfer/getData

Support in all current engines.

FirefoxYesSafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet Explorer?
Firefox AndroidYesSafari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Returns the specified data. If there is no such data, returns the empty string.

dataTransfer . setData(format, data)

DataTransfer/setData

Support in all current engines.

Firefox10+Safari5+Chrome3+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android10+Safari iOS5+Chrome Android18+WebView Android37+Samsung Internet1.0+Opera Android12+

Adds the specified data.

dataTransfer . clearData( [ format ] )

DataTransfer/clearData

Support in all current engines.

FirefoxYesSafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet Explorer?
Firefox AndroidYesSafari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Removes the data of the specified formats. Removes all data if the argument is omitted.

dataTransfer . files

DataTransfer/files

Support in all current engines.

FirefoxYesSafariYesChromeYes
OperaYesEdgeYes
Edge (Legacy)12+Internet Explorer?
Firefox AndroidYesSafari iOSNoChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

Returns a FileList of the files being dragged, if any.

DataTransfer objects that are created as part of drag-and-drop events are only valid while those events are being fired.

6.9.3.1 The DataTransferItemList interface

DataTransferItemList/DataTransferItem

Support in all current engines.

Firefox50+Safari6+Chrome13+
Opera12+Edge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android50+Safari iOS6+Chrome Android18+WebView Android4.4+Samsung Internet1.0+Opera AndroidNo

Each DataTransfer object is associated with a DataTransferItemList object.

items . length

DataTransferItemList/length

Support in all current engines.

Firefox50+Safari6+Chrome13+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android50+Safari iOS6+Chrome Android18+WebView Android4.4+Samsung Internet1.0+Opera AndroidNo

Returns the number of items in the drag data store.

items[index]

Returns the DataTransferItem object representing the indexth entry in the drag data store.

items . remove(index)

DataTransferItemList/remove

Support in all current engines.

Firefox50+Safari6+Chrome31+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android50+Safari iOS6+Chrome Android31+WebView Android4.4.3+Samsung Internet2.0+Opera AndroidNo

Removes the indexth entry in the drag data store.

items . clear()

DataTransferItemList/clear

Support in all current engines.

Firefox50+Safari6+Chrome13+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android50+Safari iOS6+Chrome Android18+WebView Android4.4+Samsung Internet1.0+Opera AndroidNo

Removes all the entries in the drag data store.

items . add(data)

DataTransferItemList/add

Support in all current engines.

Firefox50+Safari6+Chrome13+
Opera12+Edge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android50+Safari iOS6+Chrome Android18+WebView Android4.4+Samsung Internet1.0+Opera AndroidNo
items . add(data, type)

Adds a new entry for the given data to the drag data store. If the data is plain text then a type string has to be provided also.

6.9.3.2 The DataTransferItem interface

Each DataTransferItem object is associated with a DataTransfer object.

item . kind

DataTransferItem/kind

Support in all current engines.

Firefox50+Safari5.1+Chrome11+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android50+Safari iOS5+Chrome Android18+WebView Android4+Samsung Internet1.0+Opera AndroidNo

Returns the drag data item kind, one of: "string", "file".

item . type

DataTransferItem/type

Support in all current engines.

Firefox50+Safari5.1+Chrome11+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android50+Safari iOS5+Chrome Android18+WebView Android4+Samsung Internet1.0+Opera AndroidNo

Returns the drag data item type string.

item . getAsString(callback)

DataTransferItem/getAsString

Support in all current engines.

Firefox50+Safari5.1+Chrome11+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android50+Safari iOS5+Chrome Android18+WebView Android4+Samsung Internet1.0+Opera AndroidNo

Invokes the callback with the string data as the argument, if the drag data item kind is text.

file = item . getAsFile()

DataTransferItem/getAsFile

Support in all current engines.

Firefox50+Safari5.1+Chrome11+
Opera12+Edge79+
Edge (Legacy)12+Internet ExplorerNo
Firefox Android50+Safari iOS5+Chrome Android18+WebView Android4+Samsung Internet1.0+Opera AndroidNo

Returns a File object, if the drag data item kind is File.

6.9.4 The DragEvent interface

DragEvent/DragEvent

Support in all current engines.

Firefox3.5+Safari3.1+Chrome46+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidYesSafari iOSNoChrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

The drag-and-drop processing model involves several events. They all use the DragEvent interface.

event . dataTransfer

DragEvent/dataTransfer

Support in all current engines.

Firefox3.5+Safari3.1+Chrome46+
OperaYesEdge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidYesSafari iOSNoChrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

Returns the DataTransfer object for the event.

Although, for consistency with other event interfaces, the DragEvent interface has a constructor, it is not particularly useful. In particular, there's no way to create a useful DataTransfer object from script, as DataTransfer objects have a processing and security model that is coordinated by the browser during drag-and-drops.

6.9.5 Events summary

Document/drag_event

Firefox🔰 3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidNoSafari iOS11+Chrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

Document/dragend_event

Firefox🔰 3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidNoSafari iOS11+Chrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

Document/dragenter_event

Support in all current engines.

Firefox3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidNoSafari iOS11+Chrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

Document/dragleave_event

Support in all current engines.

Firefox3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidNoSafari iOS11+Chrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

Document/dragover_event

Support in all current engines.

Firefox3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidNoSafari iOS11+Chrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

Document/dragstart_event

Support in all current engines.

Firefox3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidNoSafari iOS11+Chrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

Document/drop_event

Support in all current engines.

Firefox3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox AndroidNoSafari iOS11+Chrome AndroidNoWebView AndroidNoSamsung InternetNoOpera AndroidNo

The following events are involved in the drag-and-drop model.

Event name Target Cancelable? Drag data store mode dropEffect Default Action
dragstartSource node✓ CancelableRead/write mode "none"Initiate the drag-and-drop operation
dragSource node✓ CancelableProtected mode "none"Continue the drag-and-drop operation
dragenterImmediate user selection or the body element✓ CancelableProtected mode Based on effectAllowed valueReject immediate user selection as potential target element
dragleavePrevious target elementProtected mode "none"None
dragoverCurrent target element✓ CancelableProtected mode Based on effectAllowed valueReset the current drag operation to "none"
dropCurrent target element✓ CancelableRead-only mode Current drag operationVaries
dragendSource nodeProtected mode Current drag operationVaries

Not shown in the above table: all these events bubble, are composed, and the effectAllowed attribute always has the value it had after the dragstart event, defaulting to "uninitialized" in the dragstart event.

6.9.6 The draggable attribute

Global_attributes/draggable

Support in all current engines.

Firefox2+SafariYesChromeYes
Opera12+EdgeYes
Edge (Legacy)12+Internet ExplorerYes
Firefox Android4+Safari iOSYesChrome AndroidYesWebView AndroidYesSamsung InternetYesOpera AndroidYes

All HTML elements may have the draggable content attribute set. The draggable attribute is an enumerated attribute. It has three states. The first state is true and it has the keyword true. The second state is false and it has the keyword false. The third state is auto; it has no keywords but it is the missing value default and the invalid value default.

The true state means the element is draggable; the false state means that it is not. The auto state uses the default behavior of the user agent.

An element with a draggable attribute should also have a title attribute that names the element for the purpose of non-visual interactions.

element . draggable [ = value ]

Returns true if the element is draggable; otherwise, returns false.

Can be set, to override the default and set the draggable content attribute.