Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Building an accessible auto-complete

5,666 views

Published on

This presentation for A11yBytes Camp Sydney 2017 takes a deep dive into how to create an auto-complete search function that is accessible to a range of different users including keyboard-only and screen reader users. Along the way, we will explore important keystrokes and aria attributes that can be used enhance the experience for all users.

Published in: Education
  • Well done! Very thorough, and to the point!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • @Dennis Lembree Thank you. And yes, I know others that prefer the down arrow to loop too. In the presentation I mentioned that I'd observed blind users struggle with this. One user in particular kept looping through not realising that he had gone back to the beginning. He eventually moved past this point but it concerned me that it seemed to really throw him.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Great stuff, thank you! PS: I'm actually in favor of looping options on up/down arrow press.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Building an accessible auto-complete

  1. 1. Accessible
 Autocomplete Creating
  2. 2. What is Autocomplete?
  3. 3. “Autocomplete” is a software function that provides relevant suggestions based on input by the user.
  4. 4. For this presentation, we’re going to focus on accessible autocomplete associated with search.
  5. 5. Diagram showing autosuggest search component Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA
  6. 6. The aim is to provide some information to consider if you’re thinking about building an accessible autocomplete search.
  7. 7. User Experience
  8. 8. Before diving into accessibility, 
 we’ll look at some common UX patterns associated with autocomplete search.
  9. 9. 1. There should be clear wording or visual indicators to describe the purpose of the search.
  10. 10. Are users searching across the site, an aspect of the site, a specific function?
  11. 11. Search towns in Australia Diagram showing highlighted label “Search towns in Australia”
  12. 12. 2. If additional instructions are required, they should be located in close proximity to the field.
  13. 13. Diagram showing information under the input “You can filter by Town or by State” Search towns in Australia You can filter by Town or by State
  14. 14. 3. The placeholder attribute should not be used for complex instructions.
  15. 15. This attribute it is often displayed in a faint colour and is wiped as soon as the user begins typing.
  16. 16. Search Search Towns in Australia Diagram showing placeholder “Search towns in Australia” with red cross beside placeholder
  17. 17. 4. The list of autocomplete suggestions could highlight the string typed by the user…
  18. 18. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing autosuggest options highlighting the user string
  19. 19. Or, the list could the highlight everything apart from the string typed by the user.
  20. 20. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing autosuggest options highlighting the non-user string
  21. 21. 5. It should quickly become clear to users what type of strings will trigger the autocomplete?
  22. 22. Does the search work based on the initial characters of suggestions…
  23. 23. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing autosuggest options highlighting the user string at the start of each item
  24. 24. Or any characters within the suggestion?
  25. 25. Search towns in Australia ara Araluen, NSW Bargara, QLD Bingara, NSW Coonabarabran, NSW Diagram showing autosuggest options highlighting the user string within each item
  26. 26. 6. Any autocomplete suggestions should be accurate.
  27. 27. Don't display suggestions if there is no match - unless you are trying to force users to choose from a specific set of options.
  28. 28. Search towns in Australia Banana Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing autosuggest options that do not match the user string ?
  29. 29. 7. Users should be able to easily clear the search form of previously typed strings.
  30. 30. Search towns in Australia Adaminaby, NSW Diagram showing highlighted clear component
  31. 31. 8. Ideally, there should be some clearly defined submit action associated with the search.
  32. 32. Diagram showing highlighted submit component Search towns in Australia Adaminaby, NSW
  33. 33. Keyboard-only
  34. 34. Focus
  35. 35. Any web page or web app should have clear visual indicators to help keyboard-only users determine which element is currently in focus.
  36. 36. This could just be the default browser focus ring…
  37. 37. Search towns in Australia Diagram showing input in focus - indicated with blue focus ring
  38. 38. Or by specifying your own consistent focus state methodology.
  39. 39. Search towns in Australia Diagram showing input in focus - indicated with black dotted lines
  40. 40. However, you should never make it hard or impossible for keyboard- only users to see what is in focus.
  41. 41. /* Bad practice */ input:focus { outline: none; }
  42. 42. Keystrokes
  43. 43. Keyboard-only users should be able to perform any of the following actions…
  44. 44. 1. Use the TAB keystroke to move focus into the search input field from a previous element with focus.
  45. 45. Search towns in Australia Diagram showing highlighted input TAB
  46. 46. 2. Use the TAB keystroke to move focus from the search input to the “clear” button.
  47. 47. Search towns in Australia Adaminaby, NSW Diagram showing highlighted clear button TAB
  48. 48. 3. Use the ENTER keystroke to trigger the “clear” button.
  49. 49. Search towns in Australia Adaminaby, NSW Diagram showing selected clear button ENTER
  50. 50. Note: When the “clear” button has been triggered, the search input field should be cleared and focus should shift to this field again.
  51. 51. Search towns in Australia Diagram showing focus move for clear button back to search input
  52. 52. 4. Use the TAB keystroke to move focus from the clear button to the submit button.
  53. 53. Adaminaby, NSW Search towns in Australia Diagram showing focus move form the clear button to the submit button TAB
  54. 54. 5. Use the ENTER keystroke to trigger the submit button.
  55. 55. Diagram showing selected submit button Search towns in Australia Adaminaby, NSW ENTER
  56. 56. Note: When the submit button has been triggered, focus should shift to the search result area below the autocomplete search widget.
  57. 57. Diagram showing focus move from submit button to search results Search towns in Australia Search Results Bell, NSW Bell is a small rural and residential village in the Blue Mountains region of New South Wales. Bells Beach, VIC Bells Beach is a coastal locality of Victoria, Australia iand a renowned surf beach. Bell
  58. 58. 6. Use the DOWN ARROW keystroke to move focus from the search input field to the first item in list of autocomplete suggestions.
  59. 59. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing focus move from input to first suggestion ↓ARROW
  60. 60. 7. Use the UP ARROW and DOWN ARROW keystrokes to navigate backwards and forwards through suggestions.
  61. 61. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing second selection in focus and arrows to indicate focus can move backwards or forwards ↓ARROW ↑ARROW
  62. 62. Note: The autosuggest item in focus should always be in view if there is a scrolling mechanism in place.
  63. 63. 8: Users should not be able to DOWN ARROW past the last suggestion option.
  64. 64. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing last selection in focus and red cross to indicate focus cannot go forward ↓ARROW
  65. 65. 9. Some developers allow DOWN ARROW keystrokes to loop from the last suggestion directly back to the initial input box.
  66. 66. However, I have found that some users find this confusing. They may not be aware that they have returning to the input field.
  67. 67. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing last selection in focus and red cross to indicate focus cannot jump to search input ↓ARROW
  68. 68. 10. However, users should be able to UP ARROW from the first suggestion back into the search input field.
  69. 69. Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SA Diagram showing focus move from autosuggest dropdown to search input ↑ARROW
  70. 70. 11. Use the ENTER keystrokes to select an autocomplete suggestion.
  71. 71. Diagram showing selected suggest option Search towns in Australia ar Arltunga, NT Armadale, WA Armidale, NSW Arno Bay, SAENTER
  72. 72. Note: When the ENTER keystroke has been triggered, focus should shift back to the search input field.
  73. 73. Diagram showing focus move from selected suggestion to search input field Search towns in Australia Armadale, WA
  74. 74. 12. Use the ESC keystroke to close the suggestion list and return focus to the initial input (i.e. if none of the suggestions are relevant).
  75. 75. Search towns in Australia ar Diagram showing focus returning to input ESC
  76. 76. Markup for screen readers
  77. 77. Here are some markup suggestions to make the search widget accessible to screen readers.
  78. 78. Overall
  79. 79. The widget should be wrapped inside a <form> element.
  80. 80. <form action="#"> </form>
  81. 81. The <label> and <input> elements are the core of the search button.
  82. 82. <form action="#"> <label></label> <input> </form>
  83. 83. One <button> elements will be used to “clear” user input.
  84. 84. <form action="#"> <label></label> <input> <button></button> </form>
  85. 85. A second <button> elements will be used to submit the form.
  86. 86. <form action="#"> <label></label> <input> <button></button> <button></button> </form>
  87. 87. The <ul> allows us to display the list of suggestions when appropriate.
  88. 88. <form action="#"> <label></label> <input> <button></button> <button></button> <ul> <li></li> <li></li> <li></li> </ul> </form>
  89. 89. The <div> element allows us to provide hidden instructions for screen reader users.
  90. 90. <form action="#"> <label></label> <input> <button></button> <button></button> <ul> <li></li> <li></li> <li></li> </ul> <div></div> </form>
  91. 91. The details
  92. 92. In order to explicitly associate the <label> element with the <input> element, we should use for and id attributes.
  93. 93. <label for="search">Search towns in Australia</label> <input type="text" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="false" >
  94. 94. The <input> element’s type attribute could be set to a value of "text" or "search".
  95. 95. <label for="search">Search towns in Australia</label> <input type="text" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="false" >
  96. 96. <label for="search">Search towns in Australia</label> <input type="search" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="false" >
  97. 97. However, it is important to consider how the “clear” button will operate.
  98. 98. Some browsers, like Chrome and Safari will display an <input> type of "search" with a native “clear” button at the right side of the input. Other browses like Firefox, do not.
  99. 99. Chrome Firefox Safari Diagram showing Chrome and Safari’s clear button. Firefox has no clear button.
  100. 100. More importantly, this native “clear” button often cannot be accessed via the TAB keystroke, so it is inaccessible for many Assistive Technology users.
  101. 101. So, if you want to use a robust and accessible “clear” button, it is better to use a separate <button> element.
  102. 102. Using CSS, you can make the clear button look like it sits inside the <input> element.
  103. 103. Search towns in Australia Input Button Button Diagram showing three different elements - the input, the clear and the submit button
  104. 104. Then make sure to set the type to "text" rather than "search".
  105. 105. <label for="search">Search towns in Australia</label> <input type="text" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="false" >
  106. 106. The aria-describedby attribute allows us to describe the purpose of the current element. It points the current element to a new element with a matching ID value.
  107. 107. <label for="search">Search towns in Australia</label> <input type="text" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="false" > <div id="instructions" aria-live="assertive" style="display: none;"> ... </div>
  108. 108. This allows us to provide basic instructions on the use of the widget for assistive technologies.
  109. 109. <div id="instructions" aria-live="assertive" style="display: none;"> When autocomplete options are available, use up and down arrows to review and enter to select. </div>
  110. 110. The aria-owns attribute allows us to define “a parent/child contextual relationship to assistive technologies that is otherwise impossible to infer from the DOM”.
  111. 111. In other words, we can define the <input> element as the parent, and the <ul> element as the child element.
  112. 112. <label for="search">Search towns in Australia</label> <input type="text" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="false" > <ul id="results"> ... </ul>
  113. 113. The aria-expanded attribute allows us to inform assistive technologies when the autocomplete dropdown is present. It is initially set to "false".
  114. 114. <label for="search">Search towns in Australia</label> <input type="text" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="false" >
  115. 115. This value needs to dynamically change to "true" as soon as the autocomplete suggestions are present.
  116. 116. <label for="search">Search towns in Australia</label> <input type="text" id="search" aria-describedby="instructions" aria-owns="results" aria-expanded="true" >
  117. 117. Directly after the input, we need two <button> elements.
  118. 118. The first <button> should be a type of "button" and allow users to clear the input.
  119. 119. <button type="button" aria-label="Clear"></button> <button type="submit" aria-label="Search"></button>
  120. 120. The second <button> should be a type of "submit" and allow users to submit the form.
  121. 121. <button type="button" aria-label="Clear"></button> <button type="submit" aria-label="Search"></button>
  122. 122. You may want to use icons instead of text for one or both of the buttons. In this case we are using “clear” and “search” icons.
  123. 123. Search towns in Australia Diagram showing clear and search icons
  124. 124. However, if you user icons instead of text, you will need to provide additional context for Assistive Technologies.
  125. 125. In this case, we can use aria- label attributes to provide hidden labels for both buttons.
  126. 126. <button type="button" aria-label="Clear"></button> <button type="submit" aria-label="Search"></button>
  127. 127. After the two button elements, we need to add the <ul> element which will be used to display the autocomplete suggestions.
  128. 128. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  129. 129. As mentioned before, the ID attribute’s value of "results" allows us to determine that this element is “owned” by the parent <input> element.
  130. 130. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  131. 131. The role attribute can be set with a value of "listbox", which informs assistive technologies that the element is a widget that allows the user to select one or more items from a list of choices.
  132. 132. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  133. 133. To make sure the element is initially hidden we can set the style attribute to "display:none".
  134. 134. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  135. 135. This value needs to dynamically change to something like "display:block" as soon as the autocomplete options are triggered.
  136. 136. <ul id="results" role="listbox" tabindex="0" style="display: block;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  137. 137. To make sure the element cannot be brought into focus before it is triggered, we can set the tabindex attribute to "-1".
  138. 138. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  139. 139. This value needs to dynamically change to "0" as soon as the autocomplete suggestions are present.
  140. 140. <ul id="results" role="listbox" tabindex="0" style="display: block;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  141. 141. Each of the <li> elements can be given a role attribute with a value of "option" with informs assistive technologies that they are selectable items in a select list.
  142. 142. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  143. 143. Each of the <li> elements needs to have an aria-selected attribute initially set to "false".
  144. 144. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="false">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  145. 145. This value needs to dynamically change to "true" if the individual option is selected.
  146. 146. <ul id="results" role="listbox" tabindex="-1" style="display: none;" > <li role="option" aria-selected="true">apple</li> <li role="option" aria-selected="false">banana</li> <li role="option" aria-selected="false">pear</li> </ul>
  147. 147. After the <ul> element, we have the <div> element, which has the instructions for assistive technologies.
  148. 148. <div id="instructions" aria-live="assertive" class="off-left" > When autocomplete options are available, use up and down arrows to review and enter to select. </div>
  149. 149. As mentioned before, the ID value allows us to point the <input> element to this <div> element via the aria-describedby attribute.
  150. 150. <div id="instructions" aria-live="assertive" class="off-left" > When autocomplete options are available, use up and down arrows to review and enter to select. </div>
  151. 151. The <div> element needs to be visually hidden, but still available to screen readers.
  152. 152. This can be achieved by setting it “off-left” using CSS. So, we can give it a pretend “off-left” class here.
  153. 153. <div id="instructions" aria-live="assertive" class="off-left" > When autocomplete options are available, use up and down arrows to review and enter to select. </div>
  154. 154. The aria-live attribute is set to "assertive". This informs assistive technologies as soon as anything inside this element is dynamically changed.
  155. 155. <div id="instructions" aria-live="assertive" class="off-left" > When autocomplete options are available, use up and down arrows to review and enter to select. </div>
  156. 156. We need this because the instructions will dynamically change as soon as the autocomplete options are triggered.
  157. 157. <div id="instructions" aria-live="assertive" class="off-left" > When autocomplete results are available use up and down arrows to review and enter to select. </div>
  158. 158. <div id="instructions" aria-live="assertive" class="off-left" > 6 options available. Use up and down arrows to review and enter to select. </div>
  159. 159. The instructions should also immediately change as users type if the number of suggestions changes.
  160. 160. <div id="instructions" aria-live="assertive" class="off-left" > 3 options available. Use up and down arrows to review and enter to select. </div>
  161. 161. Good examples
  162. 162. One of my favourite accessible autocomplete search widgets is the haltersweb version: https://haltersweb.github.io/Accessibility/ autocomplete.html
  163. 163. However, there are a wide range of different solutions available, such as: http://www.visionaustralia.org/digital-access-autocomplete https://a11y.nicolas-hoffmann.net/autocomplete-list/ https://alphagov.github.io/accessible-autocomplete/examples/ http://oaa-accessibility.org/examplep/combobox2/
  164. 164. Giveaways
  165. 165. I’m now going to ask you all three “prize winnable” questions.
  166. 166. The first person to correctly answer each of these questions will win a SitePoint Premium Annual Membership, with access to over $20,000 worth of SitePoint books and courses!
  167. 167. I’ll be asking the A11yBytes folks to help make sure the process is as fair as possible, but there are no guarantees!
  168. 168. Let's start with the first “prize- winnable” question...
  169. 169. Question 1
  170. 170. When should you use a link element, and when should you use a button element?
  171. 171. Answer to question 1
  172. 172. A link allows users to go somewhere. It should send the user to a new location. A button allows people to trigger some type of action such as submitting a form.
  173. 173. Question 2
  174. 174. What is the easiest and most effective way to identify common accessibility problems in your site/ app?
  175. 175. Answer to question 2
  176. 176. Unplug the mouse. The easiest and most effective way to check your site is using keyboard-only.
  177. 177. Question 3
  178. 178. What is the purpose of the aria- live attribute?
  179. 179. Answer to question 3
  180. 180. The aria-live attribute allows us to notify screen readers when content is dynamically updated in specific areas of a page.
  181. 181. Russ Weakley Max Design Site: maxdesign.com.au Twitter: twitter.com/russmaxdesign Slideshare: slideshare.net/maxdesign Linkedin: linkedin.com/in/russweakley

×