Back to docsRecipe

Accessible drag-and-drop

Build a reorderable list that works for keyboard, screen reader, and pointer users. No library required — just the HTML Drag and Drop API plus a few ARIA attributes.

Step 1 — Markup

Wrap each draggable item in a div with draggable, role="listitem", and an explicit aria-roledescription. Provide move-up / move-down buttons inside each row so keyboard users can reorder without drag.

Step 2 — Drag events

Listen for dragstart to stash the source index, dragover to permit the drop zone, and drop to splice the array. Set aria-grabbed on the active item and announce the change with a live region.

Step 3 — Live region

Keep a visually-hidden <div role="status"> that updates its text content after every move. Screen readers will speak “Item 3 moved to position 1” without stealing focus.

Step 4 — Focus management

After a keyboard reorder, move focus back to the button that triggered the action so the user can continue adjusting. Never reset focus to the top of the list.

Heads-up: The native Drag API does not fire on touch devices. For mobile support, pair with pointer events or consider a polyfill. The keyboard fallback ensures the list remains operable regardless.