dragover and drop Events
Define valid drop targets and handle the drop event.
dragover and drop Events is a free HTML Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Drop Targets Need Two Handlers
A drop target must handle both dragover (to allow the drop) and drop (to receive it). Without dragover the browser refuses to fire drop because the default behavior is "no element is a drop target".
preventDefault is Mandatory
In the dragover handler you must call e.preventDefault(). This cancels the browser default that rejects the drop. Without it the cursor stays "not allowed" and the drop event never fires no matter what the user does.
zone.addEventListener("dragover", (e) => {
e.preventDefault();
});
zone.addEventListener("drop", (e) => {
e.preventDefault();
console.log(e.dataTransfer.getData("text/plain"));
});dragenter and dragleave
dragenter fires once when the cursor enters the target; dragleave fires once when it leaves. Use them to toggle a visual "drag-over" highlight: add a class on enter, remove on leave so the user sees which area will receive the drop.
dragleave Fires for Children
A subtle quirk: moving the cursor over a child element fires dragleave on the parent followed by dragenter on the child. Use a counter incremented in dragenter and decremented in dragleave, removing the highlight only when the counter returns to zero.
let counter = 0;
zone.addEventListener("dragenter", () => {
counter++;
zone.classList.add("over");
});
zone.addEventListener("dragleave", () => {
counter--;
if (counter === 0) zone.classList.remove("over");
});Setting dropEffect
Inside dragover, set e.dataTransfer.dropEffect = "move" (or "copy", "link", "none") to control the cursor and to tell the source what will happen. The effect must be compatible with the source's effectAllowed or the drop is rejected.
Reading Data on drop
In the drop handler call e.dataTransfer.getData(format) with the same MIME type used by setData (commonly "text/plain"). Then locate the element by id, append it to the target, update a data model, or do whatever the application needs.
Preventing Default on drop
You also need e.preventDefault() in the drop handler. Without it the browser falls back to its native behavior — for a dropped URL that means navigating to the link, which immediately blows away your page state.
Drop From the Desktop
The browser converts files dragged from the OS into a drop event with e.dataTransfer.files populated. Iterate the FileList and read each file with the File API to support image uploads, log file viewers, or document importers.
zone.addEventListener("drop", (e) => {
e.preventDefault();
for (const file of e.dataTransfer.files) {
console.log(file.name, file.size);
}
});Multiple Types in dataTransfer
setData can store the same payload under several MIME types: "text/plain" for fallback, "text/uri-list" for URLs, "application/json" for structured payloads. The drop target picks the richest type it understands via getData.
Coordinating with Touch Events
Mobile browsers do not synthesize dragover/drop from touch. For a unified experience use Pointer Events plus manual hit-testing, or a library that abstracts the differences. Native HTML5 DnD is best treated as desktop-only.
Performance Tip
dragover fires continuously while the cursor moves — often dozens of times per second. Keep the handler cheap: avoid expensive DOM queries or layout reads inside it. Cache rectangles in dragenter and reuse them while the cursor stays over the target.
Knowledge Check
Why does the drop event never fire on a target until you call e.preventDefault() in the dragover handler?
Summary
A working drop target listens to dragover (always preventDefault, optionally set dropEffect) and drop (preventDefault again, then read dataTransfer.getData or dataTransfer.files). Use dragenter/dragleave with a counter for highlight, and keep handlers cheap because dragover fires very often.
Frequently asked questions
Is the “dragover and drop Events” lesson free?
Yes — the full text of “dragover and drop Events” is free to read here on the web, and the HTML Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the HTML Academy course, upgrade to CoddyKit PRO.
What will I learn in “dragover and drop Events”?
Define valid drop targets and handle the drop event. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start HTML Academy?
No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “dragover and drop Events” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this HTML Academy lesson?
Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- draggable Attribute and dragstart Event
- dragover and drop Events
- dataTransfer Object
- Practical Drag-to-Reorder List