Code examples

Use Semantic HTML

This native select contains all the accessibility criteria for free and is styled to look cool.

<div class="select-container">
  <label for="nato">
    Select a NATO Phoenetic Letter
  </label>
  <select id="nato">
    <option label="None" disabled selected>None</option>
    <option label="Alpha">Alpha</option>
    <option label="Bravo">Bravo</option>
    <option label="Charlie">Charlie</option>
  </select>
</div>

Custom elements

Custom listboxes are notoriously difficult to make screen reader accessible.

Even Angular Material documentation says “The native <select> offers the best accessibility because it is supported directly by screen-readers.”

<div id="listbox-label">
  Choose a NATO Phoenetic Letter
</div>
<button aria-haspopup="listbox"
        aria-labelledby="listbox-label listbox-button"
        id="listbox-button">
        Charlie
</button>
<ul tabindex="-1"
    role="listbox"
    aria-labelledby="listbox-label"
    class="hidden">
  <li id="alpha" role="option">
    Alpha
  </li>
  <li id="bravo" role="option">
    Bravo
  </li>
  <li id="charlie" role="option">
    Charlie
  </li>
</ul>

Developer notes

Custom listboxes are notoriously difficult to develop in a way that works for the screen reader.

Angular material custom listbox requires the Live Announcer overlay to be accessible, and advises using a native <select> for accessibility.

Before you attempt to use one of these, be certain a native <select> is not an option.

WAI-ARIA listbox examples

Name

  • The popup button should reference the label with aria-labelledby="listbox-label listbox-button"

Role

  • Use role="listbox" on the list itself.
  • Use role="option" for each list item

State

  • The state is expressed by changing the inner text of the focusable popup button

Group

  • Listboxes require a number of relationships to be built with custom attributes.
  • Use aria-haspopup="listbox" to indicate its function
  • Naming the popup button requires aria-labelledby="listbox-label listbox-button"
  • The list itself requires aria-labelledby="listbox-label" to associate options with the label.

Focus

  • Focus must be visible
  • Using the arrow keys doesn’t change the focus, it changes the name of the focusable popup button