Skip to content

Kanban Board with Drag and Drop

Dark Tailwind CSS kanban board with three task columns, native drag and drop, keyboard move buttons, live counters and screen reader announcements.

Live preview

Open in new tab

Code

A dark kanban board built with Tailwind CSS and vanilla JavaScript, with three columns (To do, In progress, Done) and task cards that move by native HTML drag and drop or by arrow buttons that work from the keyboard. Use it for sprint boards, project dashboards or content pipelines.

How it works

The root is .tkb-board. Each column is a section.tkb-column with a data-tkb-column attribute that holds its name, a heading, a counter marked data-tkb-count and a ul.tkb-list marked data-tkb-list. Every task is an li.tkb-card with draggable="true", a tag pill, an assignee avatar, a title marked data-tkb-title and two buttons with data-tkb-move="-1" and data-tkb-move="1". On phones the columns sit in a horizontal scroll-snap strip; from the md breakpoint they form a three-column grid.

The script initializes every .tkb-board on DOMContentLoaded and uses delegated listeners on the root. On dragstart it remembers the card and its original position and adds .tkb-dragging. On dragover it finds the card below the pointer by comparing clientY to each card's vertical middle and moves the dragged card there live; .tkb-over highlights the target list. If the drag ends without a drop (for example after Escape), the card returns to where it started. A click on a move button appends the card to the neighbouring column and keeps focus on the button. After every move, refresh() updates the counters and gives each button an aria-label such as "Move "Sketch onboarding screens" to In progress"; buttons in the first and last column are disabled. A :has() rule shows a "Drop tasks here" hint in empty lists.

Customization

  • data-tkb-column on each section.tkb-column: rename a column; the name is used in button labels and announcements.
  • Add a fourth section.tkb-column and change md:grid-cols-3 to md:grid-cols-4 for a Review column; the move buttons pick it up automatically.
  • bg-amber-400, bg-sky-400 and bg-emerald-400 on the heading dots: set a status color per column.
  • bg-slate-950, bg-slate-900 and bg-slate-800 on the root, columns and cards: switch to bg-slate-100, bg-white and bg-white for a light board.
  • .tkb-dragging and .tkb-over in style.css: change the look of the dragged card and the hovered drop zone.
  • content: "Drop tasks here" in style.css: change the empty-column hint text.
  • listOf(target).appendChild(card) in script.js: use prepend to place keyboard-moved cards at the top of the column.

Accessibility

Drag and drop is never the only way to move a card: the arrow buttons are real button elements with descriptive aria-label values and a visible focus-visible outline. Each column is a labelled section with a role="list" list, counters include hidden "tasks" text, and assignee initials are prefixed with hidden "Assigned to". Every move is announced through a role="status" live region. The landing highlight animation is disabled under prefers-reduced-motion: reduce.

Usage notes

Cards only move within their own .tkb-board, so several boards can share a page (use unique heading id values). To persist the order, read the cards in each data-tkb-list after refresh() runs and send them to your API with fetch().

Requirements

Add these to your page (already included in the download):

  • <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

The Tailwind browser build is for prototyping. In production, compile Tailwind with its CLI or your bundler.

Kanban Board with Drag and Drop – Tailwind CSS kanban boards component screenshot
Kanban Board with Drag and Drop · Tailwind CSS Kanban Boards