Guideline 2.1 - Keyboard Accessible
Make all functionality available from a keyboard.
Success Criterion 2.1.1 - Keyboard
All functionality of the website or app is operable through a keyboard interface without requiring specific timings for individual keystrokes.
There's an exception to this success criterion for rare situations where the underlying feature requires input that depends on the path of the user's movement and not just the endpoint. For instance, this exception applies to drawing apps.
You should ensure keyboard control for all functionality.
This doesn't necessarily mean that each control can be used from the keyboard, as long as there are ways to trigger their functionality using only the keyboard. For instance, Gmail doesn't support tabbing through your emails and controls on them but provides keyboard shortcuts for those controls instead. However, it's usually more intuitive to support tabbing through controls and using them with the keyboard, as it also provides a visual cue for your actions.
Use the following techniques to ensure keyboard control:
Native HTML form controls such as input
, select
, textarea
, buttons
, and links (a
) are accessible by default! Using semantic types (such as type="number"
) also helps assistive technologies determine the role of the fields and provide a better user experience.
<form>
<label for="name">Your name</label>
<input type="text" name="name" id="name" />
<label for="age">Your age</label>
<input type="number" name="age" id="age" />
<button type="submit">Save</button>
</form>
<a href="/help">Need help? Visit our help center.</a>
- provide keyboard-triggered event handlers
If you're using the Element click
event and the event target is focusable, the click
event will automatically trigger upon the user pressing Enter
while the target is focused.
You don't have to do additional work for focusable elements with click
handlers. If the element isn't focusable, you should also use an applicable keyboard event.
However, there are caveats: the MouseEvent
properties such as screenX
, screenY
, clientX
, clientY
or shiftKey
will fall back to their defaults and won't provide useful values, and the UIEvent.detail
property will fall back to 0
.
<button id="myClickableButton">Click (or focus me and press enter)</button>
document
.querySelector('#myClickableButton')
.addEventListener('click', (event) => console.log(event));
There could be instances where you aren't using the click
event or rely upon the MouseEvent
properties, which aren't useful for keyboard interactions.
An example of that would be if you were building a "connect the dots" game. You could implement the logic for connecting dots using a mouse by listening to mouseup
and mousedown
events and looking at their screenX
and screenY
properties. In this case, you should provide an alternative keyboard interaction mechanism. For instance, you could listen to keydown
(or keyup
, depending on how you want to handle auto-repeating) events:
<button id="d1" class="dot">.</button>
<button id="d2" class="dot">.</button>
<button id="d3" class="dot">.</button>
<button id="d4" class="dot">.</button>
const dots = document.querySelectorAll('.dot');
for (dot in dots) {
dot.addEventListener('keydown', (event) => {
if (event.keyName === ' ') {
setStartDot(event.target);
}
if (event.keyName === 'Enter') {
setEndDot(event.target);
}
});
}
Avoiding failures
Do not listen to
mousedown
,mouseup
, and other pointing device-reliant events to provide functionality without providing a keyboard interaction alternative.- This simply makes it impossible for keyboard users to use the provided functionality.
Do not remove or change focus when focus is received.
- This is sometimes done for complex form controls that combine various input types in the same user-facing form control to ensure users don't focus on the wrong field.
- However, this approach can present large issues for keyboard users, as they might need help to focus the form control properly.
- Ensure that when the focus is placed on each element, the focus remains there until the user moves it.
Find out more techniques and failures for this Success Criterion
Success Criterion 2.1.2 - No Keyboard Trap
If the focus can be moved to a component using a keyboard, then the focus can be moved away from that component using a keyboard.
If it requires more than unmodified arrow, tab keys, or other standard exit methods (like Esc
), to move focus from the component, the user should be advised how to move focus away.
Ensure that there are no keyboard traps on the page. All content on the page must meet this success criterion, as a single keyboard trap can prevent keyboard use on the whole page. There are no specific techniques to follow here: tab through the content from start to finish and ensure keyboard focus isn't trapped.
An example of a keyboard trap would be a modal that you can open from the keyboard (e.g. by pressing Enter
on its trigger), but you're only able to close by clicking on the part of the page covered by the modal, which isn't keyboard focusable. However, this often happened in the heydays of Flash and Java, with focus getting trapped in Flash objects or Java applets. It's rare to find keyboard traps these days.
Find out techniques and failures for this Success Criterion
Success Criterion 2.1.4 - Character Key Shortcuts
If a keyboard shortcut is implemented using only letters, punctuation, numbers, or symbols, you should:
- provide a way to turn the shortcut off, and/or
- provide a way to remap the shortcut to include one or more non-printable keyboard keys (e.g.
Ctrl
,Alt
), and/or - make sure the keyboard shortcut for a UI component is only active when that component has a focus.
This is to reduce accidental activation of keyboard shortcuts, common for some speech-to-text users (if the speech-to-text is active outside input fields) and people with dexterity challenges.
However, mapping keyboard shortcuts without providing a way to turn the shortcut off or remap it can also impair users using a different keyboard layout. For instance, some tools map Option + B
to move a word backward. However, this makes inputting the {
character on the Croatian keyboard layout impossible, as it's mapped to the same key combination.