Listbox with checkboxes

Associated themes :

Introduction

In this example, we start from the listbox example and we add checkboxes. We will get a component that will allow us to select an item from a list of items, just like a conventional listbox, but that allows us to check some items. We often find it in webmails.

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).

Implementation

HTML code

We take the same listbox from the listbox example and we add the ability to check / uncheck the items. For this we use the aria-checked attribute.


  <ul role="listbox" tabindex="0" aria-label="emails list">
      <li tabindex="-1" role="option" aria-checked="false">Important information about your account</li>
      ...
  </ul>

To symbolize that the item is checked, it could be very simple to do it via CSS, displaying a pictogram just before the items having the attribute aria-checked="true".

In this example, we will insert real check boxes inside each item. These will not be vocalized by the screen reader because we added the role="option" attribute (for the screen reader, it will be considered as an item no matter what you put inside it).


  <ul role="listbox" tabindex="0" aria-label="email list">
      <li tabindex="-1" role="option" aria-checked="false">
          <input tabindex="-1" type="checkbox">Important information about your account
      </li>
      ...
  </ul>

Do not forget to add the tabindex="-1" attribute to ensure that the checkboxes do not get the focus

If we want fancier checkboxes, we can use those from the Boosted library.
In this case, we must also add the label tag.


  <ul role="listbox" tabindex="0" aria-label="email list">
      <li tabindex="-1" role="option" aria-checked="false">
        <div class="form-check mb-0">
          <input tabindex="-1" id="check1" class="form-check-input" type="checkbox"><label for="check1" class="form-check-label"></label>
          Important information about your account
        </div>
      </li>
      ...
  </ul>

Note that the label tag is left blank here intentionally. Indeed, in this component, we do not want the checkbox to be selected if you click on the item label.

Interactions

To manage the interaction with the mouse, simply change the value of the aria-checked attribute when a checkbox is clicked.


document.querySelectorAll("[type=checkbox]").forEach(checkbox =>{
  checkbox.addEventListener("click",function(e){
      if(this.checked){
          this.parentElement.parentElement.setAttribute("aria-checked", "true");
      }
      else{
          this.parentElement.parentElement.setAttribute("aria-checked", "false");
      }
      e.stopPropagation();
  })
})
 

Now you must only manage the interaction with the keyboard. An item must be checked or unchecked by using the space bar. We insert this behaviour right after the code that manages the arrow keys (see the listbox example).


  document.getElementById("exempleCheckbox").addEventListener("keydown", function (e) {
    let currentItem = this.querySelector("[aria-selected=true]");
    switch(e.keyCode){
        case 38: // Up arrow
            if(currentItem.previousElementSibling !== null){
                currentItem.setAttribute("aria-selected","false");
                currentItem.previousElementSibling.setAttribute("aria-selected", "true");
                currentItem.previousElementSibling.focus();
                currentItem.previousElementSibling.classList.add('active');
            }
            e.preventDefault();
            break;
        case 40: // Down arrow
            if(currentItem.nextElementSibling !== null){
                currentItem.setAttribute("aria-selected","false");
                currentItem.nextElementSibling.setAttribute("aria-selected","true");
                currentItem.nextElementSibling.focus();
                currentItem.nextElementSibling.classList.add('active');
            }
            e.preventDefault();
            break;
case 32: // Space if (currentItem.getAttribute("aria-checked") === "true") { currentItem.setAttribute("aria-checked", "false"); currentItem.querySelector("input[type=checkbox]").checked = false; } else { currentItem.setAttribute("aria-checked", "true"); currentItem.firstElementChild.setAttribute("aria-checked", "true"); currentItem.querySelector("input[type=checkbox]").checked = true;; } e.preventDefault(); break;
} });

Example

Email list

Testing

Mouse support: you can select an item by clicking on the text. You can check or uncheck an option by clicking the checkboxes.

Keyboard support: you can select an item using the arrow up or down keys. You can check or uncheck an option using the spacebar.

Screen reader support: same keyboard shortcuts (up, down and space bar). For each item, the screen reader gives us the information whether it is selected / checked or not.

Webmail example

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

Open the webmail

Links

More information on ARIA and listbox: