HTML ondragleave Attribute

Beginner
⏱️ 5 min read
📚 Updated: Jun 2026
🎯 3 Examples
Events & Handlers

Introduction

The ondragleave attribute is an inline event handler that runs JavaScript when the dragleave event fires on a drop target. That happens when a dragged item’s pointer crosses out of the target element’s boundary. It is part of the HTML Drag and Drop API: pair a draggable="true" source with a receiver that listens for dragenter, dragover, dragleave, and drop. Use ondragleave mainly to remove visual feedback (unhighlight the zone) that ondragenter added. To allow a drop, call event.preventDefault() in dragover—not in dragleave. Watch for nested children: moving into a child fires dragleave on the parent—use an enter/leave counter or event.relatedTarget. For production sites, prefer addEventListener("dragleave", …) over inline handlers.

What You’ll Learn

01

Event handler

Inline JS.

02

dragleave event

On drop target.

03

Remove highlight

Pair with dragenter.

04

relatedTarget

True exit check.

05

addEventListener

Preferred way.

06

Counter pattern

Nested children.

Purpose of ondragleave Attribute

The primary purpose of ondragleave is to define what happens when a dragged item leaves a drop target. Common uses include removing a highlight class, resetting a status label (“Drop here” → idle), or stopping a subtle animation so users know the zone is no longer active. It connects pointer movement out of a receiver to JavaScript cleanup without a full page reload.

Do not confuse ondragleave with ondragend—that fires on the source when the drag gesture ends. dragleave fires on the target when the pointer exits its boundary. Pair it with ondragenter to add and remove highlights symmetrically. dragover fires repeatedly while hovering and is where preventDefault() enables dropping. When nested children exist, a naive dragleave handler may unhighlight too early—use a counter or check event.relatedTarget. Avoid alert() in handlers; update visible status text instead.

💡
Nested children trap

Entering a child inside the drop zone fires dragleave on the parent and dragenter on the child, which can flicker highlights. Increment a counter on dragenter, decrement on dragleave, and remove highlight only when the count reaches 0. Or skip unhighlight when zone.contains(event.relatedTarget).

📝 Syntax

Set ondragleave on a drop target or assign element.ondragleave:

ondragleave.html
<script>

  function handleDragLeave(event) {

    var zone = document.getElementById("dropZone");

    if (!zone.contains(event.relatedTarget)) {

      zone.classList.remove("over");

      document.getElementById("status").textContent = "dragleave — pointer left zone.";

    }

  }

</script>



<div draggable="true">Drag me</div>

<div id="dropZone" ondragenter="handleDragEnter(event)" ondragleave="handleDragLeave(event)">Drop zone</div>

<p id="status"></p>

Syntax Rules

  • Value is JavaScript code executed when the pointer leaves the drop target boundary.
  • dragleave fires on the drop target, not on the draggable source.
  • Pair a draggable="true" source with handlers on the receiver.
  • Call event.preventDefault() in dragover on the target to allow drop.
  • dragleave can fire when entering nested children—use a counter or relatedTarget checks.
  • JavaScript: element.ondragleave = function(event) { … }.
  • Modern alternative: element.addEventListener("dragleave", handler).

💎 Values

The ondragleave attribute accepts a string of JavaScript code:

  • ondragleave="handleDragLeave(event)" — Call a named function with the event object.
  • ondragleave="this.classList.remove('over')" — Inline statement to unhighlight the target.
  • JavaScript: zone.ondragleave = (e) => { … } assigns the handler.
  • Pair with ondragenter or a counter to add highlight when the pointer enters.
ondragleave-js.html
const zone = document.getElementById("dropZone");

let enterCount = 0;



zone.addEventListener("dragenter", (event) => {

  enterCount += 1;

  zone.classList.add("over");

  document.getElementById("status").textContent =

    "dragenter — entered drop zone.";

});



zone.addEventListener("dragleave", (event) => {

  enterCount -= 1;

  if (enterCount === 0) {

    zone.classList.remove("over");

    document.getElementById("status").textContent =

      "dragleave — left drop zone.";

  }

});



zone.addEventListener("dragover", (event) => {

  event.preventDefault();

});



document.getElementById("dropZone").ondragleave = function (event) {

  console.log("Pointer left target.", event.relatedTarget);

};

⚡ Quick Reference

EventWhen it firesHandler
dragenterPointer enters target boundaryondragenter
dragoverRepeatedly while over targetondragover
dragleavePointer leaves target boundaryondragleave
dropItem released on valid targetondrop
preventDefaultRequired in dragover to allow dropNot required in dragleave for cleanup
relatedTargetElement being entered on dragleaveUse with contains() for true exits
Nested childrendragleave may fire when entering childUse enter counter pattern

Applicable Elements

TargetSupported?Notes
<div>, <section>YesCommon drop zones; no draggable needed on target
<ul>, <li>YesSortable lists; watch nested dragleave events
<td>, <th>YesTable cell drop targets
<article>, <main>YesLarge layout drop areas
Draggable sourceSeparateSet draggable="true" on source; use ondragstart there

ondragleave vs ondragenter vs ondragover vs ondrop

HandlerWhen it firesElementTypical use
ondragenterBoundary enteredDrop targetHighlight zone, show “drop here” status
ondragoverRepeatedly while hoveringDrop targetpreventDefault() to allow drop; continuous feedback
ondragleaveBoundary leftDrop targetRemove highlight; pair with dragenter
ondropOnce when released on valid targetDrop targetAccept payload, move DOM node, update data

Examples Gallery

Inline ondragleave removing highlight paired with dragenter, dynamic element.ondragleave assignment, and the enter/leave counter pattern for nested drop zones.

👀 Live Preview

Drag the box into the drop zone, then out again. dragleave removes the highlight:

Drag this box.
Drop zone

Waiting for dragenter or dragleave…

Example — Inline ondragleave on drop zone

Remove highlight when a draggable item leaves the target boundary, paired with ondragenter:

inline-ondragleave.html
<div draggable="true">Drag me</div>

<div id="dropZone" ondragenter="handleDragEnter(event)" ondragleave="handleDragLeave(event)">Drop zone</div>

<p id="msg"></p>



<script>

  function handleDragEnter(event) {

    document.getElementById("dropZone").classList.add("over");

    document.getElementById("msg").textContent = "dragenter — entered drop zone.";

  }

  function handleDragLeave(event) {

    var zone = document.getElementById("dropZone");

    if (!zone.contains(event.relatedTarget)) {

      zone.classList.remove("over");

      document.getElementById("msg").textContent = "dragleave — left drop zone.";

    }

  }

</script>
Try It Yourself

How It Works

The browser fires dragleave on the drop target when the dragged item exits its boundary. The inline ondragleave attribute calls your cleanup function.

Dynamic Values with JavaScript

Assign the handler with element.ondragleave or addEventListener:

dynamic-ondragleave.html
<script>

  document.getElementById("dynamicDropTarget").ondragleave = function (event) {

    if (!event.currentTarget.contains(event.relatedTarget)) {

      event.currentTarget.classList.remove("over");

      document.getElementById("log").textContent =

        "Dynamic dragleave — pointer left target.";

    }

  };



  // Or preferred form:

  document.getElementById("dynamicDropTarget").addEventListener("dragleave", handler);

</script>
Try It Yourself

How It Works

Register the listener once at page load. When the pointer exits the drop target during a drag, your handler runs on the receiver element.

Example — Enter/leave counter for nested zones

Increment on dragenter, decrement on dragleave, unhighlight only when count reaches 0:

dragleave-counter.html
let enterCount = 0;



zone.addEventListener("dragenter", () => {

  enterCount += 1;

  zone.classList.add("over");

});



zone.addEventListener("dragleave", () => {

  enterCount -= 1;

  if (enterCount === 0) zone.classList.remove("over");

});



zone.addEventListener("dragover", (e) => { e.preventDefault(); });
Try It Yourself

How It Works

Each boundary crossing increments or decrements the counter. Only when enterCount === 0 does the handler remove the highlight—avoiding flicker from nested child elements.

♿ Accessibility

  • Drag is pointer-heavy — Not all users can drag with a mouse. Provide keyboard or button alternatives for the same action.
  • Announce zone state — Use aria-live regions when dragleave clears a highlight so screen reader users know the zone is inactive.
  • Avoid alert() on dragleave — Inline status text or visible UI updates are more accessible than modal alerts.
  • Do not rely on dragleave alone — Finalize important actions in accessible controls, not only after a drag gesture.
  • Visible focus — Ensure highlighted drop zones have sufficient color contrast and do not hide focus outlines on interactive elements.

🧠 How ondragleave Works

1

User drags source

dragstart fires on draggable source.

ondragstart
2

Pointer enters target

dragenter fires; add highlight on drop target.

ondragenter
3

Pointer hovers

dragover fires repeatedly; call preventDefault.

ondragover
=

Pointer exits or drops

dragleave removes highlight; drop accepts payload.

Browser Support

The dragleave event and ondragleave handler are part of the HTML Drag and Drop API and supported in all modern browsers — Chrome, Firefox, Safari, and Edge. Touch drag behavior may differ; test on your target devices.

DOM Events · Fully supported

Universal ondragleave support

All major browsers fire the underlying event and honor the ondragleave handler attribute.

99% Browser support
Google Chrome Fully supported
Full support
Mozilla Firefox Fully supported
Full support
Apple Safari Fully supported
Full support
Microsoft Edge Fully supported
Full support
Internet Explorer IE 9+ supported
Full support
Opera Fully supported
Full support
ondragleave attribute 99% supported

Bottom line: Universal support for dragleave on drop targets. Pair with dragenter, dragover + preventDefault(), and a draggable source.

💡 Best Practices

✅ Do

  • Use addEventListener on the target — Clearer than inline ondragleave.
  • preventDefault in dragover — Required on the drop target to allow dropping; not the main job of dragleave.
  • Pair dragenter and dragleave — Add highlight on enter, remove on leave for symmetric feedback.
  • Use a counter for nested zones — Avoid flicker when child elements trigger spurious dragleave events.
  • Check event.relatedTarget — Skip cleanup when the pointer moved into a descendant still inside the zone.

❌ Don’t

  • Do not use alert() — Update visible status text instead of blocking modal dialogs.

Conclusion

The ondragleave attribute runs JavaScript when a dragged item leaves a drop target and the dragleave event fires on the receiver. Use it to remove highlighting and reset status feedback—paired with ondragenter for symmetric visual states.

Prefer addEventListener("dragleave", …), use an enter/leave counter or event.relatedTarget for nested zones, call preventDefault() in dragover, and offer keyboard alternatives for accessibility.

Key Takeaways

Knowledge Unlocked

Five truths every developer should know about ondragleave

Bookmark these before wiring your next event handler.

5
Core concepts
🌐 02

Boundary exit

Pointer crosses out.

Behavior
🔄 03

Remove highlight

Pair with dragenter.

Use case
📝 04

addEventListener

Preferred.

Modern
05

Counter pattern

Nested children.

Compare

❓ Frequently Asked Questions

It runs JavaScript when the dragleave event fires on a drop target—when a dragged item’s pointer leaves that element’s boundary.
No. Call event.preventDefault() in dragover on the drop target to allow dropping. dragleave is mainly for removing visual feedback when the pointer exits.
ondragenter fires when the pointer crosses into the target boundary and adds highlight. ondragleave fires when the pointer leaves and removes highlight. Use both on the same drop target.
Moving from parent to child crosses the parent’s boundary outward, so dragleave fires on the parent even though the pointer is still inside the zone. Use an enter/leave counter or check event.relatedTarget.
Prefer element.addEventListener("dragleave", …). Inline ondragleave works for simple demos.
event.relatedTarget is the element the pointer is entering when dragleave fires. Use zone.contains(event.relatedTarget) to distinguish a true exit from a move into a nested child.

Clean up drop zones with JavaScript

Practice inline ondragleave, addEventListener, relatedTarget checks, and the counter pattern in the Try It editor.

Try ondragleave demo →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful