Learn how to make your drag and drop interfaces accessible with @dnd-kit/core
Web accessibility is about achieving feature and information parity and giving complete access to all aspects of an interface to disabled people. A digital product or website is simply not complete if it is not usable by everyone. If it excludes certain disabled populations, this is discrimination and potentially grounds for fines and/or lawsuits. – Source: Web Almanac by HTTP ArchivePeople with varying disabilities use different assistive technologies to help them experience the web. The Tools and Techniques article from the Web Accessibility Initiative (WAI) of the W3C covers how users can perceive, understand and interact with the web using different assistive technologies. Some assistive technologies for the web include:
@dnd-kit/core
library provides a number of sensible defaults to help you make your drag and drop interfaces accessible.
These sensible defaults should be seen as starting points rather than something you can set and forget; there is no one-size-fits-all solution to web accessibility.
You know your application best, and while these sensible defaults will go a long way to help making your application more accessible, in most cases you’ll want to customize these so that they are tailored to the context of your application.
The three main areas of focus for this guide to help you make your drag and drop interface more accessible are:
enter
(on Windows) or return
(on macOS) and the space
key.@dnd-kit/core
library ships with a Keyboard sensor that adheres to these guidelines. The keyboard sensor is one of the two sensors that are enabled by default on the <DndContext>
provider component.
useDraggable
listeners must be able to receive focus.
The tabindex
attribute dictates the order in which focus moves throughout the document.
tabindex
value of 0
.tabindex="0"
(for example, div
and li
elements)tabindex
attribute set to 0
if they are not natively interactive elements (such as the HTML button
element).
For this reason, the useDraggable
hook sets the tabindex="0"
attribute by default.
enter
(on Windows) or return
(on macOS) and the space
keys can be used to initiate a drag operation and pick up the draggable item.
The arrow keys are used to move the draggable item in any given direction.
After an item is picked up, it can be dropped using the enter
(on Windows) or return
(on macOS) and the space
keys.
A drag operation can be cancelled using the escape
key. It is recommended to allow users to cancel the drag operation using the escape
key for all sensors, not just the Keyboard sensor.
The keyboard shortcuts of the Keyboard sensor can be customized, but we discourage you to do so unless you maintain support for the enter
, return
and space
keys to follow the guidelines set by the third rule of ARIA.
By default, the Keyboard sensor moves in any given direction by 25
pixels when the arrow keys are pressed while dragging.
This is an arbitrary default that is likely not suited for all use-cases. We encourage you to customize this behaviour and tailor it to the context of your application using the getNextCoordinates
option of the Keyboard sensor.
For example, the useSortable
hook ships with an augmented version of the Keyboard sensor that uses the getNextCoordinates
option behind the scenes to find the coordinates of the next sortable element in any given direction when an arrow key is pressed.
In order to let users learn how to interact with draggable elements using these keyboard shortcuts, it’s important to provide screen reader instructions.
useDraggable
hook provides the role
and aria-roledescription
, and aria-describedby
attributes by default:
Attribute | Default value | Description |
---|---|---|
role | "button" | The ARIA “role” attribute lets you explicitly define the role for an element, which communicates its purpose to assistive technologies.If possible, we recommend you use a semantic <button> element for the DOM element you plan on attaching draggable listeners to. In case that’s not possible, make sure you include the role=“button” attribute, which is the default value. |
aria-roledescription | "draggable" | Defines a human-readable, localized description for the role of an element that is read by screen readers. While draggable is a sensible default, we recommend you customize this value to something that is tailored to your use-case. |
aria-describedby | "DndContext-[uniqueId]" | Each draggable item is provided a unique aria-describedby ID that points to the voiceover instructions to be read out when a draggable item receives focus |
role
and aria-roledescription
attributes can be customized via the options passed to the useDraggable
hook.
To customize the aria-describedby
instructions, refer to the section below.
<DndContext>
component renders a unique HTML element that is rendered off-screen to be used to provide these instructions to screen readers.
The default instructions are:
To pick up a draggable item, press space or enter.We recommend you customize and localize these instructions to your application and use-case using the
While dragging, use the arrow keys to move the item in any given direction.
Press space or enter again to drop the item in its new position, or press escape to cancel.
screenReaderInstructions
prop of <DndContext>
.
For example, if you were building a sortable grocery shopping list, you may want to tailor the instructions like so:
To pick up a grocery list item, press space or enter.If your application supports multiple languages, make sure you also translate these instructions. The
Use the up and down arrow keys to update the position of the item in the grocery list.
Press space or enter again to drop the item in its new position, or press escape to cancel.
<DndContext>
component only ships with instructions in English due to bundle size concerns.
<DndContext>
component renders a unique HTML element that is rendered off-screen to be used for live screen-reader announcements of events like when a drag operation has started, when a draggable item has been dragged over a droppable container, when a drag operation has ended, and when a drag operation has been cancelled.
These instructions can be customized using the announcements
prop of DndContext
.
The default announcements are:
Item with index 0 was picked up. Item was moved to index 1 of 4.Position based announcements are much more intuitive and natural:
Item at position 1 was picked up. Item was moved to position 2 of 5.
closestCenter
collision detection strategy is used, so the over
property should always be defined.
If your application supports multiple languages, make sure you also translate these announcements. The <DndContext>
component only ships with announcements in English due to bundle size concerns.