ARIA lists (listbox)

Introduction

ARIA provides a large number of components that can be used in rich interfaces (tab, accordion, slider, listbox...). In this example, we will look into the listbox component.

A listbox is a component that allows the user to select one or more items from a list.

The items of a listbox are static, a listbox is not intended to receive interactive items (such as links, buttons…), however it can contain images unlike the select.

More info: WAI-ARIA Authoring Practices.

Caution

Although improvements are being made with each new version, support for ARIA is still partial for all screen readers. Its use should be conditioned by compatibility tests on the target environments (browser/screen reader combinations).

Implemention

HTML code

To create a listbox, just apply the role listbox to a parent container. Then apply the option role to the list items. We must make it focusable for users who navigate using the keyboard (adding the tabindex="0" attribute) or adding the aria-label or aria-labelledby label for people using a screen reader. Finally, we will also add the tabindex="-1" attribute to the options so that they can receive the focus using javascript.


    <ul role="listbox" tabindex="0" aria-label="folder list">
        <li tabindex="-1" role="option">Inbox (4) <span class="sr-only">unread messages</span></li>
        <li tabindex="-1" role="option">Sent</li>
        <li tabindex="-1" role="option">Draft</li>
        <li tabindex="-1" role="option">Trash</li>          
    </ul>
      

Note that the ul and li tags could be replaced by simple div tags.

Interactions

To stick with the pattern of the ARIA listbox (WAI-ARIA Authoring Practices), we must handle some interactions using JavaScript.

When taking the focus, if no item is selected, it should automatically select the first item. If an item is already selected when the listbox receives the focus, it must move the focus to it.


       $("[role=listbox]").on("focus", function () {
           // If no selected element, select the first by default
           if (!$(this).find("[aria-selected=true]").length) {               
                $(this).find("[role=option]:first").attr("aria-selected", "true").focus();
           } else {
               $(this).find("[aria-selected=true]").focus();
           }
        });
      

We will then handle the keyboard interaction:


    $("[role=listbox]").on("keydown", function (e) {            
        var currentItem = $(this).find("[aria-selected=true]");          
        switch (e.keyCode) {
            case 38:  // Up arrow
                if (currentItem.prev().length) {
                    currentItem.attr("aria-selected", "false");                    
                    currentItem.prev().attr("aria-selected", "true").focus();
                }                    
                e.preventDefault();
                break;
            case 40: // Down arrow
                if (currentItem.next().length) {
                    currentItem.attr("aria-selected", "false");
                    currentItem.next().attr("aria-selected", "true").focus();
                }
                e.preventDefault();
                break;
        }
    });
      

Finally, we have to handle the mouse. When clicked, it sets the attribute aria-selected.


    $("[role=option]").on("mousedown", function (e) {
        $(this).parent().find("[aria-selected=true]").attr("aria-selected", "false");
        $(this).attr("aria-selected", "true");
        e.preventDefault();
    });
      

We customize the mouse pointer when the mouse is over an item.


    [role=option] {
        cursor: pointer;
    }
      

Example

Here is an example implementing the code above.

List of mail folders

Testing

Mouse support: you can select an item from the list using the mouse.

Screen reader support: with NVDA, it is possible to scroll through the items in the list, it is also possible to know the item being selected.

Tab key support: you can access the list, then the up and down arrow keys move the selection. However, the Shift+Tab keys should move the focus toward the top of the page, instead, it is blocked inside the list.

Fixing keyboard navigation

When the focus is positioned on a list item, the Shift+Tab key combination brings up the focus to the first focusable element, in this case it is the listbox element. But as soon as the listbox receives the focus, it automatically moves the focus on the selected item.

To correct the problem, simply make listbox unfocusable once one of the list item has got the focus.


       $("[role=option]").on("focus", function (e) {
           $(this).parent().attr("tabindex", "-1");
       });
       
       $("[role=option]").on("blur", function (e) {
           $(this).parent().attr("tabindex", "0");
       });
      

working example

List of email folders

Testing

Mouse support: OK

Screen reader support: OK

Keyboard support: OK

Webmail example

Here is a static prototype that implements the listbox component of this example and the example with a listbox with checkboxes .

Open the webmail

Links

More information on ARIA and listbox: