Drag and Drop List JavaScript: Build Reorderable UI

Learn to build accessible, robust drag-and-drop lists in JavaScript. This guide covers HTML5 DnD, keyboard accessibility, React/state patterns, and library-based approaches with working code and best practices.

JavaScripting
JavaScripting Team
·5 min read
Drag & Drop UI - JavaScripting
Quick AnswerDefinition

Drag and drop list JavaScript enables users to reorder list items (or move them between lists) by dragging with a mouse or touch. You can implement it with the HTML5 Drag and Drop API for full control, or use a library like SortableJS for feature-rich, cross-browser support. This article covers core patterns, accessibility, and practical, working code examples.

Core concepts and API surface

Drag and drop interactions in the browser hinge on draggable elements, a set of drag events, and a data model that reflects the visual order. The HTML5 Drag and Drop API gives you low-level control, while libraries abstract away edge cases across browsers. According to JavaScripting, solving drag-and-drop lists well starts with a clear data model and predictable reordering rules. In this section we cover the essential concepts and a minimal, working example that ties DOM moves to a data array.

HTML
<ul id="dragList" aria-label="Draggable items" role="list"> <li role="listitem" draggable="true" data-id="a1">Item A</li> <li role="listitem" draggable="true" data-id="a2">Item B</li> <li role="listitem" draggable="true" data-id="a3">Item C</li> </ul>
JavaScript
// Minimal DnD setup: attach listeners to the list element const list = document.getElementById('dragList'); let dragSrcEl = null; function onDragStart(e) { dragSrcEl = e.target; e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/plain', e.target.dataset.id); if (e.dataTransfer.setDragImage) { const ghost = e.target.cloneNode(true); ghost.style.opacity = '0.5'; document.body.appendChild(ghost); e.dataTransfer.setDragImage(ghost, 0, 0); } } function onDragOver(e) { e.preventDefault(); // allow drop e.dataTransfer.dropEffect = 'move'; return false; } function onDrop(e) { e.preventDefault(); const target = e.target; if (dragSrcEl && target && target !== dragSrcEl) { target.parentNode.insertBefore(dragSrcEl, target); } } list.addEventListener('dragstart', onDragStart); list.addEventListener('dragover', onDragOver); list.addEventListener('drop', onDrop);
  • This block shows draggable items and basic event wiring. In real apps, map DOM moves to your data model and re-render to reflect the new order. Variations include placeholders, multi-drag, or drops across multiple lists.

wordCountEncrypted":null}

prerequisites packaging note? :null

Steps

Estimated time: 60-90 minutes

  1. 1

    Define UI and data model

    Outline the list structure in HTML and create a corresponding array in JavaScript that mirrors the visible order. This ensures a single source of truth for reordering.

    Tip: Map every DOM item to a stable id in your data model.
  2. 2

    Enable dragging and extract IDs

    Mark list items draggable and propagate the item id through dataTransfer so drops can map back to data indices.

    Tip: Avoid relying on innerText for identity.
  3. 3

    Handle drag over and drop events

    Prevent default on dragover to allow dropping and implement drop logic that reorders the DOM and updates your data model.

    Tip: Keep DOM movement behind a function to simplify testing.
  4. 4

    Add keyboard accessibility

    Provide ARIA roles and keyboard handlers to move items, not just mouse users.

    Tip: Use role=list and role=listitem for assistive tech.
  5. 5

    Sync state with UI

    After a drop, update the underlying array and re-render the list to reflect the new order.

    Tip: Prefer a pure function reorder(list, from, to) to keep logic testable.
  6. 6

    Test across devices

    Verify behavior on desktop and touch devices, and adjust for touch events if needed.

    Tip: Test with screen readers and ensure focus management remains intuitive.
Pro Tip: Use a stable key in React or framework bindings to prevent unnecessary re-renders during reordering.
Warning: Always provide keyboard/accessibility support; visual drag alone excludes keyboard users.
Note: Add a visual placeholder or animation to clarify where the item will drop.

Prerequisites

Required

Keyboard Shortcuts

ActionShortcut
Focus next draggable itemWithin a list that supports keyboard navigation
Move focus to previous itemWithin accessible list navigation+
Grab item with keyboardSelects an item to simulate dragging
Move item with arrowsReorder using keyboard when an item is focusedArrowUp / ArrowDown
Cancel dragCancel or reset current drag operationEsc

Questions & Answers

What is a drag and drop list in JavaScript?

A drag and drop list in JavaScript lets users reorder elements by dragging them with a pointer or keyboard. The HTML5 DnD API provides core capabilities, while libraries offer higher-level behavior and cross-browser reliability. The pattern combines DOM changes with a synchronized data model.

A drag and drop list lets users reorder items by dragging with a mouse, touch, or keyboard. It uses the DnD API or libraries and keeps your data in sync with the UI.

Which libraries are best for drag-and-drop lists?

Several libraries offer robust drag-and-drop patterns, such as SortableJS, React Beautiful DDnD, and dnd-kit. Choose based on project needs, accessibility, and performance. In simple projects, HTML5 DnD may be enough; for complex lists, a library can streamline state management and advanced features.

Libraries like SortableJS or dnd-kit simplify complex drag-and-drop lists and offer built-in accessibility and performance improvements.

How do I make drag-and-drop accessible?

Provide semantic roles (list and listitem), keyboard navigation (Arrow keys to move, Space to grab, Esc to cancel), and ARIA attributes to convey state. Keep focus visible and ensure all actions are possible with a keyboard, not just a mouse.

Make DnD accessible by adding proper roles, keyboard navigation, and clear focus indicators for screen readers and keyboard users.

How can I reorder items in React without external state?

Maintain a single source of truth (state array) and implement a pure reorder function that returns a new array when a drag ends. Then set the new array to state to trigger re-render with the updated order.

Keep a single array in state and reorder it via a pure function when a drag finishes, then re-render the list.

What about touch devices and performance?

Ensure touch events map to drag-and-drop semantics, use CSS transforms for smooth motion, and minimize layout thrashing. Consider virtualization for long lists and debouncing rapid reorder updates.

Make DnD feel smooth on touch with transforms and careful performance tuning; consider virtualization for large lists.

What to Remember

  • Define a clear data model first
  • Provide both mouse and keyboard interactions
  • Keep DOM moves in sync with your data state
  • Test accessibility across devices

Related Articles