Source Code

<div class="kb-board" id="kbBoard">
  <div class="kb-column" data-status="todo">
    <div class="kb-col-header">
      <span class="kb-col-title">To Do</span>
      <span class="kb-col-count" id="kbCountTodo">0</span>
    </div>
    <div class="kb-col-body" data-status="todo"></div>
  </div>
  <div class="kb-column" data-status="progress">
    <div class="kb-col-header">
      <span class="kb-col-title">In Progress</span>
      <span class="kb-col-count" id="kbCountProgress">0</span>
    </div>
    <div class="kb-col-body" data-status="progress"></div>
  </div>
  <div class="kb-column" data-status="done">
    <div class="kb-col-header">
      <span class="kb-col-title">Done</span>
      <span class="kb-col-count" id="kbCountDone">0</span>
    </div>
    <div class="kb-col-body" data-status="done"></div>
  </div>
</div>

Kanban Drag & Drop Board — Free HTML CSS JS Snippet

Kanban Drag & Drop Board · Dashboards · Plain HTML, CSS & JS · Live preview

What's included

Features

Native HTML5 drag-and-drop API — draggable, dragstart, dragover, drop, dragend — no external library
Single TASKS array as source of truth; the board re-renders from data rather than manually moving DOM nodes
Live per-column count badges that update immediately after every drop
Visual drag-over highlight on the column currently being hovered
Faded, scaled visual state on the card actively being dragged
Color-coded tag pills per task for quick scanning
Fully self-contained vanilla JS with no external dependencies

About this UI Snippet

Kanban Drag & Drop Board — Native HTML5 Drag-and-Drop Task Board

Screenshot of the Kanban Drag & Drop Board snippet rendered live

This snippet is a small kanban board — three columns holding draggable task cards that can be moved between "To Do", "In Progress", and "Done" purely with the browser's built-in drag-and-drop API, no library involved.

How the drag lifecycle works

Each card is a div with draggable="true". Its dragstart handler stores the card's task id in event.dataTransfer.setData('text/plain', task.id) and adds a .kb-dragging class for a faded, slightly-scaled visual state; dragend removes that class regardless of whether the drop succeeded. Each column body listens for dragover, calling preventDefault() (required for a drop to be permitted at all) and toggling a .kb-drag-over highlight class on the parent column; dragleave removes that highlight.

A single source of truth drives the DOM

Rather than manually moving the dragged DOM node, the drop handler reads the task id back out of dataTransfer, finds the matching task object in the TASKS array, updates its status field, and calls renderBoard() to fully re-render all three columns from that array. This keeps the board's visual state always in sync with a single JS data model instead of drifting between DOM state and data state.

Live counts

Each column header shows a badge with its current card count. updateCounts() runs after every render, reading the live child count of each column body directly from the DOM, so the numbers are always accurate after a drop.

Step by step

How to Use

  1. 1
    Load the snippetClick "Kanban Drag & Drop Board" in the sidebar to load its HTML, CSS, and JS into the editor panels. The preview updates instantly.
  2. 2
    Edit the codeModify any panel — HTML, CSS, or JS. The preview refreshes as you type. Use Reset in each panel header to restore the original.
  3. 3
    Preview on devicesClick the Mobile (375px), Tablet (768px), or Desktop buttons in the preview header to check responsiveness.
  4. 4
    Export in your formatClick "HTML" to download a standalone file, "JSX" for a React component, "Tailwind" for a React + Tailwind CSS component, "Tailwind HTML" for a standalone HTML file with Tailwind CDN, "Vue" for a Vue 3 SFC with <template>/<script setup>/<style scoped>, or "Angular" for a standalone Angular .component.ts file. "Copy all" copies the full code to clipboard.
  5. 5
    Save your versionClick "Save as", type a name, and press Enter. Your snippet saves to IndexedDB and appears in the Saved tab.

Real-world uses

Common Use Cases

Project management dashboards
The core interaction pattern behind tools like Trello, Jira boards, and Linear.
Reference for HTML5 drag-and-drop
A clean example of dataTransfer, dragover preventDefault, and drop handling.
Internal task trackers
Drop into an admin panel or internal tool that needs simple status-based task movement.
Teaching state-driven UI updates
Shows re-rendering from a data model instead of manually mutating the DOM on drop.

Got questions?

Frequently Asked Questions

Each column body element carries a data-status attribute. The drop handler reads that attribute off the column the event fired on and assigns it to the matching task object before re-rendering.

Browsers block dropping onto an element by default. Calling preventDefault() inside dragover is required to signal that the element is a valid drop target, which is what makes the drop event fire at all.

No, this implementation moves cards between columns by status. Reordering within a column would need additional logic comparing drop position against sibling card positions.

The dragstart handler adds a .kb-dragging class that reduces opacity and scale slightly; dragend removes it whether the drop succeeded or was cancelled.