Accessibility
Introduction
If you're new to accessibility for the web, the Web Almanac by HTTP Archive has an excellent primer on the subject and the state of web accessibility that you should read before diving into this guide: https://almanac.httparchive.org/en/2021/accessibility
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 Archive
People 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:
Screen readers
Voice control
Screen magnifiers
Input devices (such as the keyboard, pointers and switch devices)
When building accessible interfaces for the web, it's important to keep the three following questions in mind:
Identity: What element is the user interacting with?
Operation: How can the user interact with the element?
State: What is the current state of the element?
In this guide, we'll focus on how to make drag and drop interfaces that are keyboard accessible and provide identity, operation instructions and live state updates for screen readers.
Building accessible drag and drop interfaces
Building drag and drop interfaces that are accessible to everyone isn't easy, and requires thoughtful consideration.
The @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:
Keyboard support
One of the five rules of ARIA is that all interactive ARIA controls must be usable with the keyboard.
When creating widgets that a user can click or tap, drag, and drop, a user must also be able to navigate to the widget and perform an equivalent action using the keyboard.
For drag and drop interfaces, this means that the activator element that initiates the drag action must:
Be able to receive focus
A user must be able to activate the action associated with the element using both the
enter
(on Windows) orreturn
(on macOS) and thespace
key.
Both these guidelines should be respected to comply with the third rule of ARIA.
The @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.
Focus
In order for the Keyboard sensor to function properly, the activator element that receives the useDraggable
listeners must be able to receive focus.
The tabindex
attribute dictates the order in which focus moves throughout the document.
Natively interactive elements such as buttons, anchor tags and form controls have a default
tabindex
value of0
.Custom elements that are intended to be interactive and receive keyboard focus need to have an explicitly assigned
tabindex="0"
(for example,div
andli
elements)
In other words, in order for your draggable activator elements to be able to receive keyboard focus, they need to have the 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.
Keyboard shortcuts
Once a draggable activator element receives focus, the 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.
Screen reader instructions
In order to users know how to interact with draggable items using only the keyboard, it's important to provide information to the user that their focus is currently on a draggable item, along with clear instruction on how to pick up a a draggable item, how to move it, how to drop it and how to cancel the operation.
Role
To let users know that their focus is currently on a draggable item, the useDraggable
hook provides the role
and aria-roledescription
, and aria-describedby
attributes by default:
The 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.
Instructions
By default, each <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. 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.
We recommend you customize and localize these instructions to your application and use-case using the 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. 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.
If your application supports multiple languages, make sure you also translate these instructions. The <DndContext>
component only ships with instructions in English due to bundle size concerns.
Screen reader announcements using live regions
Live regions are used to notify screen readers of content changes.
When building accessible drag and drop interfaces, live regions should be used to provide screen reader announcements in real-time of time-sensitive information of what is currently happening with draggable and droppable elements without having to move focus .
By default, each <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:
While these default announcements are sensible defaults that should cover most simple use cases, you know your application best, and we highly recommend that you customize these to provide a screen reader experience that is more tailored to the use case you are building.
When authoring screen reader announcements that rely on an element's position (index) in a list, use positions rather than indices to describe the element's current position.
Here's an example of index based announcements and why you should avoid them:
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.
For example, when building a sortable list, you could write custom announcements that are tailored to that use-case using position based announcements:
The example above assumes that the 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.
Last updated