Accessibility
Every draggable can be moved with the keyboard, with nothing to enable. The exception is an item that is itself a text field, a select, a checkbox or an editable element, which needs a focusable drag handle (see below).
Keyboard
A hidden list is one that is still in the page but not shown: display: none on it or an ancestor (an inactive tab, a column hidden by a media query), visibility: hidden, or a size of zero. Pointer drags skip hidden lists too: the drag falls through to the list underneath, if any, as it does for a disabled list.
Pressing Space in a control inside an item, such as a text field or a button, types into or clicks that control and does not pick the item up, unless the control is the drag handle. The same goes for an item that is itself a text field, textarea, select, checkbox or editable element: Space types into it, toggles it or opens it, and only Space on a focusable drag handle inside it picks it up (see Interactive children). So such an item needs one:
- An
input,textareaorselectcan't hold a handle. Make a row element the draggable instead and put the control inside it. - A
[contenteditable]draggable without a focusable handle can't be moved with the keyboard. Give it a handle such as<span class="grip" contenteditable="false" tabindex="0" role="button" aria-label="Drag block">.
After a keyboard drop or cancel, focus returns to the draggable element itself. For an editable block that puts the caret in the block; press Tab to reach a grip inside it again.
Moving past the edge of the visible area scrolls the list to show where the item will land, so the keyboard reaches every item, not just the rendered ones. A list of plain @for rows scrolls the containers around it, nearest first.
Managed for you
tabindex="0"on draggables (-1when disabled)- After a keyboard drag, focus returns to the moved item in its new position
aria-grabbedon draggables andaria-dropeffect="move"on droppables
aria-grabbed and aria-dropeffect are deprecated since ARIA 1.1, and most screen readers ignore them. They do not tell screen reader users that an item can be dragged, how to drag it, or where it is. Add instructions and announcements yourself, as described below.
Instructions
Nothing tells a screen reader user that Space picks an item up. Describe the keys once in a hidden element and point every draggable at it with aria-describedby. Screen readers read the description when the item gets focus:
Screen reader announcements
The library does not make announcements itself, so wording and translations stay in your hands. The events carry everything you need: (dragStart) for the pick-up, (placeholderMove) for every step and (dragEnd) for the result. Render the messages in a live region:
.sr-only is the usual visually-hidden utility (position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);).
With multiple lists, also name the list in the step message: event.droppableId is the list the placeholder is in.
Touch
Touch drags work out of the box. If your lists also need to scroll by touch, add a short dragDelay so a quick swipe scrolls and a press-and-hold drags.