DEV Community

loading...
Cover image for The problem with autocomplete and how to fix it

The problem with autocomplete and how to fix it

savvasstephnds profile image Savvas Stephanides ・3 min read

About

Autocomplete is an amazing tool for your website. It helps your users find what they're looking for, much faster than they would if they typed everything and clicked the Search button.

For example, if I'm using a search engine for capital cities called "Capital Search" to search for "Nicosia", instead of typing the whole name and clicking Search, I can just type the first 2-3 letters ("nic") and the result will show up right under the text box. Now I can just click it and it will take me straight to the website!

Autocomplete showing the result for Nicosia

Interactive page available on CodePen

However this instant interaction with your users comes with a small but important issue.

Quick overview of our autocomplete code

Before we explore the problem with autocomplete, let's explore how our code currently looks like. The full code is available here. The way it works is quite simple:

  1. The user types on the input field
  2. Every time they type, a list of capital cities is filtered to get a list of all capital cities starting with the user's input string. For example if I type "n", the cities of "Nassau", "Nicosia", "Nairobi" etc. get returned as search results.
  3. The results are shown as a list under the input box.
  4. Clicking on an item takes the user to the city's Wikipedia page.

The problem

The issue with autocomplete has to do with accessibility, specifically with screen reader software. Every time a user types on the input box, the state of the page changes: the results from autocomplete are updated and presented to your user.

Progression of autocomplete search results while typing the word "Amsterdam"

However, the screen reader does not recognise this as an action to tell the user about. It will announce the header ("Capital Search") and the input box when they gain focus, but not the search results.

You, as the developer, will need to put something in place in order to tell the screen reader user how many results have been found while typing the search.

The solution: "Live regions"

The solution for this problem is what we call an "ARIA live region". We're basically using the aria-live tag to create a <div>. Whenever this tag is included, the screen reader will announce any change happening to its contents. It looks like this:

<div role="region" aria-live="polite">0 results found</div>
Enter fullscreen mode Exit fullscreen mode

If the content changes to "2 results found", the screen reader will let the user know.

Updating our code

Now we need to update our code from the CodePen link above to include our live region.

First, let's add the region to our HTML:

<div id="page">
  <div id="container">
    <h1>Capital Search</h1>
    <div id="search">
      <div id="autocomplete">
        <input type="text" id="query" onkeyup="respondToSearchboxChange()"/>
        <ul id="results">
        </ul>
      </div>
    </div>
  </div>

</div>
+ <div id="live-region" role="region" aria-live="polite"></div>
Enter fullscreen mode Exit fullscreen mode

Now we need to update our Javascript code to update our live region every time there's a change in search results:

function respondToSearchboxChange(){
  var input = document.querySelector("#query").value

  var searchResults = []


  if(input.length > 0){
    searchResults = capitals.filter((capital) => capital.toLowerCase().startsWith(input))
  }
+  
+  document.querySelector("#live-region").innerHTML = `${searchResults.length} results found`

  document.querySelector("ul#results").innerHTML = searchResults.map((result) =>
    `<li><a href="https://en.wikipedia.org/wiki/${result}" target="_blank" rel="noreferrer">${result}</a></li>`
  ).join("")
}
Enter fullscreen mode Exit fullscreen mode

Finally, since we don't want the region to be visible on the page itself, we are going to hide it using CSS:

#live-region{
    position: fixed;
    top: -100px;
}
Enter fullscreen mode Exit fullscreen mode

Full code available on CodePen

That's it! Your autocomplete is now ready and accessible to screen reader users. Every time the result count changes, the screen reader will let the user know. Awesome!

Let me know, either here or on Twitter, how you found this tutorial. Have it helped you make your autocomplete function more accessible?

Discussion

pic
Editor guide
Collapse
siddhantk232 profile image
Siddhant Kumar

interesting... thanks for sharing this awesome knowledge. One question, how can I enable the reader to read the <li />s in the suggestions box (<ul />)? Is this handled by the screen reader automatically?

Collapse
savvasstephnds profile image
Savvas Stephanides Author

Hello Siddhant! Thank you for reading, I'm glad you found it useful.

The important thing here is to make sure the search results are available immediately after the input box. That is, the user can reach the search result list with a click of the tab button when the input box is in focus.

Collapse
giorgosk profile image
Giorgos Kontopoulos πŸ‘€

Thanks Savvas nice one.
Why only include the count and not the results themselves in the live-region though ?

Collapse
savvasstephnds profile image
Savvas Stephanides Author

Thanks Giorgo! πŸ˜ƒ

Very good question!

The reason I haven’t included the results themselves is because the search could potentially return 10-20 results or even more. If the screen reader reads every single result, it will overwhelm the user. So a much simpler β€œ2 results found” etc. is much better.

Collapse
giorgosk profile image
Giorgos Kontopoulos πŸ‘€

Thanks I got it
Perhaps one can include the results only if it is 1 or 2 to help further with accesibility.

Thread Thread
savvasstephnds profile image
Savvas Stephanides Author

That’s actually not a bad idea πŸ˜ƒπŸ‘

Collapse
phongduong profile image
Phong Duong

Awesome. Thank you for sharing

Collapse
nayanagrawal79 profile image
NAYAN AGRAWAL

Interesting!!

Collapse
savvasstephnds profile image