H

HTML Handbook

Clean • Professional

HTML Drag & Drop API

3 minute

HTML Drag & Drop API

The Drag and Drop API allows users to drag elements (like images, files, or text) and drop them into another area on the page. It makes web apps more interactive.

Key Features:

  • Works with HTML attributes draggable="true".
  • Lets users drag elements and drop them on a page
  • Used in file uploaders, task boards (Trello), and image galleries.

How Drag & Drop Works

  • Add draggable="true" to make an element draggable.
  • Use events on draggable items: dragstart, drag, dragend.
  • Use events on drop targets: dragenter, dragover, dragleave, drop.
  • Call event.preventDefault() in dragover to allow dropping.
  • Use event.dataTransfer to pass information (e.g., the dragged element’s ID or file data).

Core Concepts & Events

  • draggable attribute: enables dragging on an element.
<div draggable="true">Drag me</div>
  • Key events
    • dragstart: set data with dataTransfer.setData(...)
    • dragover: call preventDefault() to enable drop
    • drop: read data with dataTransfer.getData(...)
  • dataTransfer object
    • setData(type, data) / getData(type)
    • files (when dragging files from desktop)
    • Optional: setDragImage(img, x, y) to customize the drag ghost image

Example 1: Basic Drag a Box into a Drop Zone

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Drag Box</title>
  <style>
    #box {
      width: 80px; height: 80px;
      background: tomato;
      margin: 20px; cursor: grab;
    }
    #dropZone {
      width: 200px; height: 150px;
      border: 2px dashed #666;
      text-align: center; padding-top: 50px;
    }
  </style>
</head>
<body>
  <h3>Drag the box into the drop zone</h3>
  <div id="box" draggable="true"></div>
  <div id="dropZone">Drop here</div>

  <script>
    const box = document.getElementById("box");
    const dropZone = document.getElementById("dropZone");

    box.addEventListener("dragstart", (e) => {
      e.dataTransfer.setData("text/plain", "box");
    });

    dropZone.addEventListener("dragover", (e) => e.preventDefault());
    dropZone.addEventListener("drop", (e) => {
      e.preventDefault();
      dropZone.textContent = "Box Dropped!";
    });
  </script>
</body>
</html>

Output :

learn code with durgesh images

Example 2: Drag-and-Drop File Upload (Preview Images)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>File Upload</title>
  <style>
    #fileZone {
      width: 300px; height: 150px;
      border: 2px dashed #666;
      text-align: center; padding-top: 50px;
      margin-bottom: 10px;
    }
    #preview img { max-width: 100px; margin: 5px; }
  </style>
</head>
<body>
  <h3>Drag and drop images</h3>
  <div id="fileZone">Drop images here</div>
  <div id="preview"></div>

  <script>
    const fileZone = document.getElementById("fileZone");
    const preview = document.getElementById("preview");

    fileZone.addEventListener("dragover", (e) => e.preventDefault());
    fileZone.addEventListener("drop", (e) => {
      e.preventDefault();
      const files = e.dataTransfer.files;
      for (let file of files) {
        if (file.type.startsWith("image/")) {
          const reader = new FileReader();
          reader.onload = (event) => {
            const img = document.createElement("img");
            img.src = event.target.result;
            preview.appendChild(img);
          };
          reader.readAsDataURL(file);
        }
      }
    });
  </script>
</body>
</html>

Output :

learn code with durgesh images

Example 3: Custom Drag Image (Ghost)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Custom Drag Image</title>
  <style>
    #dragMe {
      width: 100px; height: 100px;
      background: teal; color: white;
      text-align: center; line-height: 100px;
      cursor: grab;
    }
    #dropTarget {
      margin-top: 20px;
      width: 250px; height: 120px;
      border: 2px dashed gray;
      text-align: center; padding-top: 40px;
    }
  </style>
</head>
<body>
  <h3>Custom ghost image while dragging</h3>
  <div id="dragMe" draggable="true">Drag me</div>
  <div id="dropTarget">Drop here</div>

  <script>
    const dragMe = document.getElementById("dragMe");
    const dropTarget = document.getElementById("dropTarget");

    dragMe.addEventListener("dragstart", (e) => {
      const ghost = document.createElement("div");
      ghost.style.width = "80px";
      ghost.style.height = "80px";
      ghost.style.background = "orange";
      ghost.style.borderRadius = "50%";
      document.body.appendChild(ghost);
      e.dataTransfer.setDragImage(ghost, 40, 40);
      setTimeout(() => ghost.remove(), 0);
    });

    dropTarget.addEventListener("dragover", (e) => e.preventDefault());
    dropTarget.addEventListener("drop", (e) => {
      e.preventDefault();
      dropTarget.textContent = "Dropped with custom ghost!";
    });
  </script>
</body>
</html>

Output :

learn code with durgesh images

Example 4: Sortable List (Reorder Items)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Sortable List</title>
  <style>
    ul { list-style: none; padding: 0; }
    li {
      padding: 10px; margin: 5px;
      background: lightblue;
      cursor: move;
    }
  </style>
</head>
<body>
  <h3>Reorder the items by dragging</h3>
  <ul id="sortable">
    <li draggable="true">Item 1</li>
    <li draggable="true">Item 2</li>
    <li draggable="true">Item 3</li>
    <li draggable="true">Item 4</li>
  </ul>

  <script>
    const sortable = document.getElementById("sortable");
    let draggedItem = null;

    sortable.addEventListener("dragstart", (e) => {
      draggedItem = e.target;
    });

    sortable.addEventListener("dragover", (e) => {
      e.preventDefault();
      const target = e.target;
      if (target.tagName === "LI" && target !== draggedItem) {
        const rect = target.getBoundingClientRect();
        const next = (e.clientY - rect.top) / (rect.height) > 0.5;
        sortable.insertBefore(draggedItem, next ? target.nextSibling : target);
      }
    });
  </script>
</body>
</html>

Output :

learn code with durgesh images

Browser Support & Limitations

  • Works in all major desktop browsers.
  • Mobile support is inconsistent for native DnD. Prefer Pointer Events or custom touch logic for a great mobile UX.
  • File drops (from OS to browser) rely on dataTransfer.files.

Article 0 of 0