The HTML Drag and Drop API lets users select a draggable element with the mouse, drag it, and drop it on a droppable element. A translucent ghost of the item follows the pointer. You customize what can be dragged, what data is transferred, and which HTML elements accept drops.
What are the three parts of a drag?
Every operation involves (1) the item being dragged, (2) the data in the drag data store, and (3) the drop target. Dragging within a page, into a page (files), or out of a page share the same event model with slightly different requirements.
What does HTML markup add?
The draggable attribute marks custom sources. Images, links, and text selections are already draggable by default. A page script listens for drag events and updates the DOM on drop.
When should you use it?
Kanban cards, reordering lists, moving items between panels, or accepting file drops onto an HTML zone. For touch-first mobile apps, plan for limited native support or a dedicated library.
Drop zones need preventDefault on dragover.
Without it, the browser shows a “fly back” and never fires drop.
Text selection changes.
When an element is draggable="true", normal click-drag selects less easily—users may need Alt (or the keyboard) to select text inside it.
Data store timing.
Write with setData only in dragstart. Read with getData only in drop.
Syntax
HTML Syntax for Drag and Drop
Mark a source, then wire events in a script:
draggable.html
<element draggable="true">
HTML
<p id="p1" draggable="true">This element is draggable.</p>
<p id="target">Drop Zone</p>
<script>
var p1 = document.getElementById("p1");
var target = document.getElementById("target");
p1.addEventListener("dragstart", function (ev) {
ev.dataTransfer.setData("text/plain", ev.target.innerText);
});
target.addEventListener("dragover", function (ev) {
ev.preventDefault(); // required to allow drop
});
target.addEventListener("drop", function (ev) {
ev.preventDefault();
ev.target.append(ev.dataTransfer.getData("text/plain"));
});
</script>
Reference
Core HTML Concepts
Building blocks of drag-and-drop on a webpage:
Concept
Role
draggable="true"
Makes a custom HTML element a drag source
Default draggables
Images, links, and selections (browser-defined data)
DataTransfer
Drag data store: text items (and files) with MIME types
setData / getData
Write in dragstart; read in drop
Drop target
Element that calls preventDefault on dragover
DragEvent
Event object passed to drag handlers (dataTransfer)
Drag events on HTML elements
Event
Fires when…
On
dragstart
Dragging begins
Dragged item
drag
Item is moving (repeatedly)
Dragged item
dragenter
Pointer enters an element
Potential target
dragleave
Pointer leaves an element
Potential target
dragover
Item over an element (repeatedly)
Potential target
drop
User releases on a valid target
Drop target
dragend
Drag operation ends
Dragged item
dragstart / drag / dragend do not fire when dragging a file into the browser from the OS. Target events do not fire when dragging out of the page.
Approach
How to Add Drag and Drop to an HTML Page
Follow this order for a working in-page drag.
Add HTML for the source (draggable="true") and the drop zone.
On dragstart, call dataTransfer.setData("text/plain", …) (and optional other types).
On the drop zone, dragover → preventDefault() so drop is allowed.
On drop, preventDefault(), getData, and update the HTML.
On dragend, reset source styles (opacity, classes).
Optional: highlight the zone on dragenter / dragover, clear on dragleave / drop.
Goal
HTML / script pattern
Make a div draggable
<div draggable="true">…</div>
Pass text
e.dataTransfer.setData("text/plain", text)
Allow drop
dragover → e.preventDefault()
Read on drop
e.dataTransfer.getData("text/plain")
Disable link drag
<a draggable="false" href="…">
Try it
Live Preview
Drag the blue card onto the dashed zone. Uses the same HTML attributes and events as a real page.
demo
Source has draggable="true". Zone calls preventDefault on dragover.
Drag onto the zone
Drag me
Drop here
Waiting for drop…
Code
HTML Examples
Six patterns: enable dragging, set data, drop zones, dragend cleanup, hover highlight, and a full demo.
drop reads the string and updates the zone’s text.
Edge Cases & Pitfalls
Most “drop does nothing” bugs are missing preventDefault or wrong event timing for dataTransfer.
dragover
Forgot preventDefault on dragover
The drop never fires. Always cancel default on the intended HTML drop zone.
data
Reading data outside drop
The store is unreadable on most events. Set in dragstart; get in drop.
touch
Mobile / touch
Native HTML5 DnD is desktop-oriented. Plan pointer/touch alternatives for phones.
files
OS file drops
No dragstart on the page. Handle drop and read dataTransfer.files.
select
Text selection inside draggables
Dragging may capture the gesture. Document Alt/keyboard selection for content editors.
a11y
Keyboard accessibility
Mouse DnD alone is not enough. Offer buttons or keyboard moves for the same HTML actions.
Compatibility
Browser Support
The HTML Drag and Drop API (draggable, DragEvent, DataTransfer) is supported in all modern desktop browsers.
✓ Desktop · Widely available
Drag and Drop in HTML
draggable elements and drop targets work across current desktop browsers; touch support varies.
DesktopHTML DnD API
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
HTML Drag and DropWide
Bottom line: Build desktop HTML DnD with confidence—always preventDefault on dragover, and plan separately for touch.
Remember
Key Takeaways
draggable="true" marks custom HTML drag sources.
preventDefault on dragover is required for drops.
setData in dragstart; getData in drop.
dragend resets source styles whether the drop succeeded or not.
One line: Mark HTML with draggable → set data on dragstart → allow drop with dragover → update the page on drop.
Frequently Asked Questions
It is a browser API that lets users pick up HTML elements (or default-draggable items like images and links), drag them, and drop them onto a target. You mark sources with draggable="true", listen for drag events, and handle drop on the target.
Add the HTML attribute draggable="true". Images and links are draggable by default; other elements need this attribute. Set draggable="false" to disable dragging on images or links.
Call event.preventDefault() in the dragover handler on the drop zone. Without that, the browser refuses the drop. Also set data in dragstart with setData if you need to read it in drop.
event.dataTransfer holds the drag data store. In dragstart, use setData(type, string). In drop, use getData(type). Types are usually text/plain or text/html. You can only write during dragstart and read during drop.
dragover fires repeatedly while the item is over a potential target—use it to preventDefault and show hover styles. drop fires once on release over a valid target—read data and update the HTML.
Desktop browsers support it well. Touch support is limited. For mobile-first UIs, consider pointer events or libraries that add touch-friendly drag behavior.