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.

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.
<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>// 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
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
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
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
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
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
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.
Prerequisites
Required
- Required
- Code editor (e.g., VS Code)Required
- Basic knowledge of HTML5 Drag and Drop API or a library like SortableJSRequired
Optional
- Optional
Keyboard Shortcuts
| Action | Shortcut |
|---|---|
| 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 focused | ArrowUp / ArrowDown |
| Cancel dragCancel or reset current drag operation | Esc |
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