Stop 06 · Browser APIsTopics · 11/13

Drag Drop

Part of the Frontend Developer Roadmap

In short

Dragging cards across a Kanban board or dropping files onto an upload box feels natural. The browser has drag and drop built in, with a few rules to learn.

The native HTML Drag and Drop API (`draggable`, `dragstart`, `drop`, etc.) lets users drag elements or files around the page — the basis of reorderable lists and file-drop zones. Native drag-and-drop has several event and browser quirks, so understanding the underlying API is useful even when a production application later adopts a dedicated library.

The jaadu mascot in a white cap hands a steel tiffin to someone waiting at a door.

Think of it like this

The dabbawala handover

One dabbawala picks up the tiffin and its code says where it's going. At the destination, someone has to be ready to receive it, or it can't be handed over. In drag and drop, the drop zone must say 'I'm ready' too.

Watch it happen

The life of a drag

Card
dataTransfer
Done column

setData("task-1")

1/5dragstart: the user grabs the card and you store its id in the drag's dataTransfer.

The big ideas

What you need to know

draggable="true"

Links and images drag by default. For other elements, add the draggable attribute.

Carry data with it

In dragstart, use e.dataTransfer.setData to attach info, like the card's id.

Allow the drop

The drop zone must call e.preventDefault() in dragover. Without it, drop never fires.

Touch and keyboard

Native drag and drop can be patchy on touch screens and doesn't work by keyboard. Offer a button alternative too.

See it in code

Walk through the code

js
1// <div class="card" draggable="true" id="task-1">Fix navbar</div>2document.addEventListener("dragstart", (e) => {3  if (e.target.matches(".card")) e.dataTransfer.setData("text/plain", e.target.id);4});5 6document.querySelectorAll(".column").forEach((col) => {7  col.addEventListener("dragover", (e) => e.preventDefault()); // allow drop8  col.addEventListener("drop", (e) => {9    e.preventDefault();10    const id = e.dataTransfer.getData("text/plain");11    col.appendChild(document.getElementById(id));12  });13});

1/3When any card starts dragging, attach its id to the drag as plain text.

For dropping files from the desktop, read e.dataTransfer.files in the drop handler instead. It's a FileList, same as a file input.

Save yourself the pain

Common mistakes

Oops

Adding a drop listener and wondering why it never fires.

Do this instead

Call e.preventDefault() in the dragover handler. That's what marks the element as a valid drop zone.

Oops

Dropping a file and having the browser open it in the tab.

Do this instead

Call e.preventDefault() in drop as well, so the browser doesn't take over.

Your mission

Mini Kanban board

~40 min

Quick check

Your drop zone's drop event never fires. What's the most likely cause?

Go deeper

  1. 1Build a simple drag-and-drop file upload zone. Keep the first version small, then add one improvement after the core behavior works.
  2. 2Make a list of items reorderable using native drag-and-drop events. Validate your understanding by applying it in a small practical example.
  3. 3Consider a library (dnd-kit, react-beautiful-dnd) for complex cases — the native API is fiddly.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge