Listbox Example
This example page is incomplete; it is not ready for review. When ready, feedback will be welcome in issue 123.
The following two example implementations of the design pattern for listbox demonstrate differences between single-select and multi-select functionality. In both examples, users can use action buttons to move options from one list to another. In the first implementation, users can choose a single option and then activate an action button while in the second example, they may select multiple options before activating an action button.
Examples
Example 1: Single-Select Listbox
Rank features important to you when choosing where to live. If a feature is unimportant, move it to the unimportant features list.
- Proximity of public K-12 schools
- Proximity of child-friendly parks
- Proximity of grocery shopping
- Proximity of fast food
- Proximity of fine dining
- Neighborhood walkability
- Availability of public transit
- Proximity of hospital and medical services
- Level of traffic noise
- Access to major highways
Notes
- Assistive technologies are told which option in the list is visually focused by the value of
aria-activedescendant
:- DOM focus remains on the
listbox
element. - When a key that moves focus is pressed or an option is clicked, JavaScript changes the value of
aria-activedescendant
on thelistbox
element. - If the
listbox
element does not contain any options,aria-activedescendant
does not have a value.
- DOM focus remains on the
- When Tab moves focus into either listbox:
- If none of the options are selected, the first option receives focus.
- If an option is selected, the selected option receives focus.
- Only one option may be selected at a time (have
aria-selected="true"
). -
As the user moves focus in the list, selection also moves.
That is, both the value of
aria-activedescendant
and the element that hasaria-selected="true"
change.
Example 2: Multi-Select Listbox
Choose upgrades for your transport capsule.
- Leather seats
- Front seat warmers
- Rear bucket seats
- Rear seat warmers
- Front sun roof
- Rear sun roof
- Privacy cloque
- Food synthesizer
- Advanced waste recycling system
- Turbo vertical take-off capability
Notes
- Like in example 1, assistive technologies are told which option in the list is visually focused by the value of
aria-activedescendant
:- DOM focus remains on the
listbox
element. - When a key that moves focus is pressed or an option is clicked, JavaScript changes the value of
aria-activedescendant
on thelistbox
element. - If the
listbox
element does not contain any options,aria-activedescendant
does not have a value.
- DOM focus remains on the
- When Tab moves focus into either listbox:
- If none of the options are selected, focus is set on the first option.
- If one or more options are selected, focus is set on the first selected option.
- Unlike example 1, more than one option may be selected at a time (have
aria-selected="true"
).- The multi-select capability is communicated to assistive technologies by setting
aria-multiselectable="true"
on thelistbox
element. - All option elements have a value set for
aria-selected
. - Selected options have
aria-selected
set totrue
and all others have it set tofalse
. - Keys that move focus do not change the selected state of an option.
- The multi-select capability is communicated to assistive technologies by setting
- Users can toggle the selected state of the focused option with Space or click.
Example 3: Scrollable Listbox
Choose your favorite transuranic element (actinide or transactinide).
- Neptunium
- Plutonium
- Americium
- Curium
- Berkelium
- Californium
- Einsteinium
- Fermium
- Mendelevium
- Nobelium
- Lawrencium
- Rutherfordium
- Dubnium
- Seaborgium
- Bohrium
- Hassium
- Meitnerium
- Darmstadtium
- Roentgenium
- Copernicium
- Nihonium
- Flerovium
- Moscovium
- Livermorium
- Tennessine
- Oganesson
Notes
- This example has a
listbox
with more options than its height can accommodate. - Scrolling only works as expected if the listbox is the options'
offsetParent
. The example usesposition: relative
on the listbox to that effect. - When an option is focused that isn't (fully) visible, the listbox's scroll position is updated:
- If Up Arrow or Down Arrow is pressed, the previous or next option is scrolled into view.
- If Home or End is pressed, the listbox scrolls all the way to the top or to the bottom.
- If
focusItem
is called, the focused option will be scrolled to the top of the view if it was located above it or to the bottom if it was below it. - If the mouse is clicked on a partially visible option, it will be scrolled fully into view.
- When a fully visible option is focused in any way, no scrolling occurs.
- Normal scrolling through any scrolling mechanism (including Page Up and Page Down) works as expected.
The scroll position will jump as described for
focusItem
if another means than a mouse click is used to change focus after scrolling. - This example uses a single-select listbox, but works just as well with a multi-select listbox.
Other Accessibility Features
- Keyboard shortcuts for action buttons:
- Action buttons have the following shortcuts:
- "Up": Alt + Up Arrow
- "Down": Alt + Down Arrow
- "Add": Enter
- "Not Important", "Important", and "Remove": Delete
- Availability of the shortcuts is communicated to assistive technologies via the
aria-keyshortcuts
property on the button elements. - Each shortcut is only captured when focus is in a context where it is relevant. For example, Enter performs an add only when focus is in the available options list, and Delete performs a remove only when focus is in the chosen options list.
- Using a shortcut key intentionally places focus to optimize both screen reader and keyboard usability. For example, pressing Alt + Up Arrow in the "Important Features" list keeps focus on the option that is moved up, enabling all keyboard users to easily perform consecutive move operations for an option and screen reader users to hear the position of an option after it is moved. Similarly, pressing Enter in the available options list leaves focus in the available options list. If the option that had focus before the add operation is no longer present in the list, focus lands on the first of the subsequent options that is still present.
- Action buttons have the following shortcuts:
- In example 1, since there are four action buttons, a toolbar widget is used to group all the action buttons into a single tab stop.
Keyboard Support
- Down Arrow: Moves focus to the next option.
- Up Arrow: Moves focus to the previous option.
- Home: Moves focus to first option.
- End: Moves focus to last option.
Multiple selection keys supported in example 2:
- Space: changes the selection state of the focused option .
- Shift + Down Arrow: Moves focus to and selects the next option.
- Shift + Up Arrow: Moves focus to and selects the previous option.
- Control + Shift + Home: Selects from the focused option to the beginning of the list.
- Control + Shift + End: Selects from the focused option to the end of the list.
- Control + A: selects all options in the list. If all options are selected, unselects all options.
Role, Property, State, and Tabindex Attributes
Attribute | Applied to Element | Usage |
---|---|---|
role="listbox" |
ul |
Identifies the focusable element that has listbox behaviors and contains the listbox options. |
aria-labelledby="ID_REF" |
ul |
Applied to the element with the listbox role, it refers to the span containing its label. |
tabindex="0" |
ul |
Applied to the element with the listbox role, it puts the listbox in the tab sequence. |
aria-multiselectable="true" |
ul |
Example 2 only: Applied to the element with the listbox role, tells assistive technologies that the list supports multiple selection. The default value is false so it is not specified in example 1. |
aria-activedescendant="ID_REF" |
ul |
Applied to the element with the listbox role, tells assistive technologies which of the options, if any, is visually indicated as having keyboard focus.
DOM focus remains on the ul element and the idref specified for aria-activedescendant refers to the li element that is visually styled as focused.
When navigation keys, such as Down Arrow, are pressed, the JavaScript changes the value.
When the listbox is empty, aria-activedescendant="" .
|
role="option" |
li |
Identifies each selectable element containing the name of an option. |
aria-selected="true" |
li |
Applied to elements with role option that are visually styled as selected to inform assistive technologies that the options are selected. In example 1, this is always the same option that is referenced by aria-activedescendant because it is a single-select listbox where selection follows focus. In example 2, more than one option may be selected so the user can move focus among options without effecting which options are selected. Thus in example 2, the focus style and selection styles are distinctly different and independent. |
aria-selected="false" |
li |
Example 2 only: Applied to elements with role option that are not visually styled as selected to inform assistive technologies that the options are selectable but not selected. In example 1, this is not necessary because the focus cannot move to an unselected option. |
The following attributes are commonly useful when implementing the listbox design pattern but are not used in these examples.
aria-setsize
andaria-posinset
: Since all option elements are present in the DOM, the browser is able to calculate these values automatically and provide them to assistive technologies.aria-orientation
: The default orientation for a listbox is vertical so it is not necessary to specify a value.
Javascript and CSS Source Code
- CSS: listbox.css
- Javascript: listbox.js
HTML Source Code
Example 1: Single-Select Listbox
<p>
Rank features important to you when choosing where to live. If a feature is unimportant, move it to the unimportant features list.
</p>
<div class="listbox-area">
<div class="left-area">
<span id="ss_imp_l">
Important Features:
</span>
<ul id="ss_imp_list"
tabindex="0"
role="listbox"
aria-labelledby="ss_imp_l">
<li id="ss_opt1" role="option">
Proximity of public K-12 schools
</li>
<li id="ss_opt2" role="option">
Proximity of child-friendly parks
</li>
<li id="ss_opt3" role="option">
Proximity of grocery shopping
</li>
<li id="ss_opt4" role="option">
Proximity of fast food
</li>
<li id="ss_opt5" role="option">
Proximity of fine dining
</li>
<li id="ss_opt6" role="option">
Neighborhood walkability
</li>
<li id="ss_opt7" role="option">
Availability of public transit
</li>
<li id="ss_opt8" role="option">
Proximity of hospital and medical services
</li>
<li id="ss_opt9" role="option">
Level of traffic noise
</li>
<li id="ss_opt10" role="option">
Access to major highways
</li>
</ul>
<div role="toolbar" aria-label="Actions">
<button id="ex1-up"
class="toolbar-item selected"
aria-keyshortcuts="Alt+ArrowUp"
aria-disabled="true">
Up
</button>
<button id="ex1-down"
class="toolbar-item"
tabindex="-1"
aria-keyshortcuts="Alt+ArrowDown"
aria-disabled="true">
Down
</button>
<button id="ex1-delete"
class="toolbar-item move-right-btn"
tabindex="-1"
aria-keyshortcuts="Alt+ArrowRight Delete"
aria-disabled="true">
Not Important
</button>
</div>
</div>
<div class="right-area">
<span id="ss_unimp_l">
Unimportant Features:
</span>
<ul id="ss_unimp_list"
tabindex="0"
role="listbox"
aria-labelledby="ss_unimp_l"
aria-activedescendant="">
</ul>
<button id="ex1-add"
class="move-left-btn"
aria-keyshortcuts="Alt+ArrowLeft Delete"
aria-disabled="true">
Important
</button>
</div>
</div>
Example 2: Multi-Select Listbox
<p>
Choose upgrades for your transport capsule.
</p>
<div class="listbox-area">
<div class="left-area">
<span id="ms_av_l">
Available upgrades:
</span>
<ul id="ms_imp_list"
tabindex="0"
role="listbox"
aria-labelledby="ms_av_l"
aria-multiselectable="true">
<li id="ms_opt1"
role="option"
aria-selected="false">
Leather seats
</li>
<li id="ms_opt2"
role="option"
aria-selected="false">
Front seat warmers
</li>
<li id="ms_opt3"
role="option"
aria-selected="false">
Rear bucket seats
</li>
<li id="ms_opt4"
role="option"
aria-selected="false">
Rear seat warmers
</li>
<li id="ms_opt5"
role="option"
aria-selected="false">
Front sun roof
</li>
<li id="ms_opt6"
role="option"
aria-selected="false">
Rear sun roof
</li>
<li id="ms_opt7"
role="option"
aria-selected="false">
Privacy cloque
</li>
<li id="ms_opt8"
role="option"
aria-selected="false">
Food synthesizer
</li>
<li id="ms_opt9"
role="option"
aria-selected="false">
Advanced waste recycling system
</li>
<li id="ms_opt10"
role="option"
aria-selected="false">
Turbo vertical take-off capability
</li>
</ul>
<button id="ex2-add"
class="move-right-btn"
aria-keyshortcuts="Alt+ArrowRight Delete"
aria-disabled="true">
Add
</button>
</div>
<div class="right-area">
<span id="ms_ch_l">
Upgrades you have chosen:
</span>
<ul id="ms_unimp_list"
tabindex="0"
role="listbox"
aria-labelledby="ms_ch_l"
aria-activedescendant=""
aria-multiselectable="true">
</ul>
<button id="ex2-delete"
class="move-left-btn"
aria-keyshortcuts="Alt+ArrowLeft Delete"
aria-disabled="true">
Remove
</button>
</div>
</div>
Example 3: Scrollable Listbox
<p>
Choose your favorite transuranic element (actinide or transactinide).
</p>
<div class="listbox-area">
<div class="left-area">
<span id="ss_elem">
Transuranium elements:
</span>
<ul id="ss_elem_list"
tabindex="0"
role="listbox"
aria-labelledby="ss_elem">
<li id="ss_elem_Np" role="option">
Neptunium
</li>
<li id="ss_elem_Pu" role="option">
Plutonium
</li>
<li id="ss_elem_Am" role="option">
Americium
</li>
<li id="ss_elem_Cm" role="option">
Curium
</li>
<li id="ss_elem_Bk" role="option">
Berkelium
</li>
<li id="ss_elem_Cf" role="option">
Californium
</li>
<li id="ss_elem_Es" role="option">
Einsteinium
</li>
<li id="ss_elem_Fm" role="option">
Fermium
</li>
<li id="ss_elem_Md" role="option">
Mendelevium
</li>
<li id="ss_elem_No" role="option">
Nobelium
</li>
<li id="ss_elem_Lr" role="option">
Lawrencium
</li>
<li id="ss_elem_Rf" role="option">
Rutherfordium
</li>
<li id="ss_elem_Db" role="option">
Dubnium
</li>
<li id="ss_elem_Sg" role="option">
Seaborgium
</li>
<li id="ss_elem_Bh" role="option">
Bohrium
</li>
<li id="ss_elem_Hs" role="option">
Hassium
</li>
<li id="ss_elem_Mt" role="option">
Meitnerium
</li>
<li id="ss_elem_Ds" role="option">
Darmstadtium
</li>
<li id="ss_elem_Rg" role="option">
Roentgenium
</li>
<li id="ss_elem_Cn" role="option">
Copernicium
</li>
<li id="ss_elem_Nh" role="option">
Nihonium
</li>
<li id="ss_elem_Fl" role="option">
Flerovium
</li>
<li id="ss_elem_Mc" role="option">
Moscovium
</li>
<li id="ss_elem_Lv" role="option">
Livermorium
</li>
<li id="ss_elem_Ts" role="option">
Tennessine
</li>
<li id="ss_elem_Og" role="option">
Oganesson
</li>
</ul>
</div>
</div>