Autocomplete widgets can be helpful for accessibility because they can make it easier to enter text by providing suggestions based on the characters initially typed. This particularly helps people who find typing more difficult and people who may be susceptible to spelling mistakes.
Creating an accessible integrated autocomplete widget is a complex process. You need to ensure that screen-reader users are notified when the list of suggestions appears and that they can enter the list and select an option using the keyboard.
One solution is to use an ARIA live region to announce when autocomplete options are available, and to create a listbox
containing the options that appear as the user types, which is controlled with the up and down arrow keys.
Example
For this example, we’re manually implementing autocomplete for a “choose your pet” input. To begin with, the markup should look like this:
<form>
<label for="pets">Choose a pet</label>
<div class="suggestions-container">
<div class="suggestions-help" role="status" aria-live="polite"></div>
<input id="pets" data-suggest type="text" autocomplete="off" aria-autocomplete="list">
<div class="suggestions"></div>
</div>
</form>
Note the .suggestions-help
live region and .suggestions
, which will need to be populated with the listbox
(where applicable) on the input
event. Also note autocomplete="off"
, which suppresses native autocomplete functionality that could get in the way of our custom UI. The ARIA property of aria-autocomplete="list"
replaces the semantics so that “autocomplete” is announced on focus.
$('[data-suggest]').on('input', function() {
// handle suggestions here
});
In the code editor example you’ll see an array of pet types. As the user types, the input
event listens for changes and compares the entered value to each item in the pets array. If there are matches, the first thing the script does is alert the user using the live region:
if (!_.isEmpty(suggestions)) {
$('.suggestions-help', scope).text(
'There are '+suggestions.length+' suggestions. Use the up and down arrows to browse.');
}
}
This tells the user how many suggestions are available (suggestions.length
) and—importantly—how to choose from those suggestions. The newly populated listbox
is made focusable using tabindex="0",
and it is focused if the user presses the down arrow key. In this state, list’s markup looks like this:
<div role="listbox" tabindex="0" aria-activedescendant="pets-0">
<div id="pets-0" role="option" tabindex="-1">hamster</div>
<div id="pets-1" role="option" tabindex="-1">hermit crab</div>
<div id="pets-2" role="option" tabindex="-1">horse</div>
</div>
Note the listbox
role and that each child of the listbox
has a role of option
. This is the only way that a listbox
will provide the correct information to screen readers.
Also note that the listbox
has a property called aria-activedescendant
. This keeps track of the “active” option as the user searches through the options with the up and down keys. It uses the current option’s id
as its value, and that value is updated with JavaScript. That way, whenever a new option is made active, screen readers should announce the option’s text, such as “cat,” and the index of the option, such as “two of three.”
To choose the selected list option, the user can hit enter, which clears the list of options from the listbox
and refocuses the input field:
if (e.keyCode == 13) {
e.preventDefault();
e.stopPropagation();
$('#pets').focus();
}
Code editor
See this custom autocomplete implementation in a code editor. Try operating it with just your keyboard, with a screen reader running at the same time.
See the Pen autocomplete input controls by HUIT - Web, UX and Digital Accessibility Services (@hwpdas) on CodePen.