HTML Tutorial · HTML5 Features · Lesson 30 of 34
HTML Drag and Drop
Make elements draggable and handle drops with the HTML Drag and Drop API, plus a keyboard alternative.
The basics
- Mark an element
draggable="true". - In
dragstart, put data onevent.dataTransfer. - On the drop target, call
preventDefault()indragover(this allows dropping). - In
drop, read the data and update the page.
<style>
.col { display: inline-block; vertical-align: top; width: 140px; min-height: 120px; border: 2px dashed #999; margin: 4px; padding: 6px; }
.col.over { background: #eef2ff; }
.task { background: #fde68a; padding: 4px 6px; margin: 4px 0; cursor: grab; }
</style>
<div class="col" id="todo"><b>To do</b>
<div class="task" draggable="true" id="t1">Write docs <button data-move="t1">Done</button></div>
<div class="task" draggable="true" id="t2">Fix bug <button data-move="t2">Done</button></div>
</div>
<div class="col" id="done"><b>Done</b></div>
<script>
const done = document.getElementById("done");
document.querySelectorAll(".task").forEach((t) =>
t.addEventListener("dragstart", (e) => e.dataTransfer.setData("text/plain", t.id)));
done.addEventListener("dragover", (e) => { e.preventDefault(); done.classList.add("over"); });
done.addEventListener("dragleave", () => done.classList.remove("over"));
done.addEventListener("drop", (e) => {
e.preventDefault();
done.classList.remove("over");
done.append(document.getElementById(e.dataTransfer.getData("text/plain")));
});
// keyboard and touch alternative
document.addEventListener("click", (e) => {
const id = e.target.dataset.move;
if (id) { done.append(document.getElementById(id)); e.target.remove(); }
});
</script>
Files
Dropping files from the desktop works the same way: read event.dataTransfer.files in the drop handler, as upload areas do.
Accessibility
Drag and drop needs a pointer. Always provide a keyboard and touch alternative, such as "Move to Done" buttons or a select menu. The example includes one.
Test yourself
Why must the drop target call preventDefault() in its dragover handler?
To stop the page scrollingBy default elements don't accept drops; cancelling dragover allows droppingTo copy the dragged dataIt's optional and has no effect
Show answer
Answer: By default elements don't accept drops; cancelling dragover allows dropping
Without it, the drop event never fires.