An enhanced textbox that allows free text input, selection from a list, or a combination of both. Hence the name 'combobox'.
A combobox is a composite pattern containing a textbox, listbox and button.
A combobox may optionally have autocomplete behaviour.
- Feb 22nd, 2016
- Issue with Safari and Voiceover not announcing combobox options is now fixed.
- May 13th, 2016
- Developer Guide added
You can take a look at the combobox pattern in action on our examples site.
You can get an idea of the required markup structure by viewing our bones project.
Each row in the list of options allows only a single action. It is not possible to have multiple actions per row, e.g. select, edit and delete.
Combobox keyboard focus will appear to be in two places at the same time (the textbox and the listbox). In actual fact, keyboard focus always stays on the textbox. The aria-activedescendant property controls the pseudo-focus inside of the listbox.
With keyboard focus on the combobox, down arrow key will expand the listbox.
Alternatively, you may wish to auto-expand the listbox as soon as focus lands on the combobox. In this case, you may wish to exclude the button.
There is no strict requirement for the combobox button to be in the keyboard tabindex. This is because the listbox can be expanded using the down arrow key.
Up and down arrow keys navigate the list of options.
Pressing ENTER key on any option will set the combobox value and close the list of options.
Pressing ESC key will close the listbox if visible, otherwise clear the textbox value.
The screen reader will announce the input as 'text edit', 'combobox' or words to those effect, depending on level of ARIA support.
When keyboard focus is on the textbox, screen reader should announce "n suggestions available. Use up and down arrow keys to navigate" - or words to those effect. Typically this instructional text is not provided by screen readers and so must be coded in page.
Mouse and Touch
Clicking or tapping the combobox button will toggle the listbox display.
Alternatively, you may wish to auto-expand the listbox when tapping inside the combobox input.
Clicking or tapping an option will fill the combobox with that value. For long forms, the list of options must close without triggering form submit.
We start with a label and textbox:
<span class="combobox" id="combobox-0"> <label for="combobox_0-input">Game Console</label> <input id="combobox_0-input" name="console" type="text" placeholder="Playstation 4, Xbox One, etc."/> <!-- button goes here --> <!-- description goes here --> <!-- listbox goes here --> </span>
We have added our elements inside of a
A button, description and listbox elements will be appended to this wrapper. It is up to you whether you wish to render these elements server-side or client-side. There are pros and cons to both approaches, which we will discuss below.
The button should immediately follow the textbox. This button allows mouse and touch users to expand the combobox.
<button type="button" disabled>Expand</button>
At the time of writing, screen readers don't do a good job of letting the user know how to interact with a combobox or how many options it contains. To solve this problem, we can add offscreen text.
<span id="combobox_0-description" class="clipped">Combobox has 6 options. Use up and down keys to navigate.</span>
It is strongly recommended to add this description element on the client-side, and only after we are sure the widget is fully functional.
Next, in order for the screen reader to announce this description, we must add an
<input id="combobox_0-input" name="console" type="text" placeholder="Playstation 4, Xbox One, etc." aria-describedby="combobox_0-description" />
Now the screen reader announces the description whenever focus lands on the combobox.
If the number of options changes based on the value of the combobox (i.e. filtering occurs) this new information must be related to assistive technology. The description element can be converted to a live region in order to achieve this.
<span id="combobox_0-description" class="clipped" role="status" aria-live="polite">Combobox has 6 options. Use up and down keys to navigate.</span>
The new attributes are
Note: aria-live attribute is technically redundant here, because status role has an implicit aria-live setting of
polite. We add it to double-up on our support for older browsers and AT that might not support the status role.
After the description, we add the listbox of options. The listbox may render on the server or the client. Like the disabled button above, it is wise to put the listbox in a semantically hidden state if rendering on the server. To do so, use the
aria-hidden state (or HTML5
<ul id="combobox_0-listbox" role="listbox" aria-hidden="true"> <li role="option" id="nid-0">Playstation 3</li> <li role="option" id="nid-1">Playstation 4</li> <li role="option" id="nid-2">Xbox 360</li> <li role="option" id="nid-3">Xbox One</li> <li role="option" id="nid-4">Wii</li> <li role="option" id="nid-5">Wii U</li> </ul>
<input id="combobox-0-input" name="console0" type="text" placeholder="Playstation 4, Xbox One, etc." role="combobox" aria-expanded="false" autocomplete="off" aria-owns="combobox_0-listbox" aria-describedby="combobox_0-instructions">
The new attributes are
Our elements are now in place, but how does a keyboard user navigate to the options? We cannot use TAB key because focus must stay on the combobox (so that user can type characters). As with any widget, the answer lies in the arrow keys. Up and down arrow keys are the way to select our combobox options.
If focus must remain on the combobox, how then do we also have focus on the listbox options? The answer is that we don't. Focus always remains on the combobox and instead we have a kind of pseudo-focus on the options. We call the option with pseudo-focus the active descendant. And guess what? Yes, there is an ARIA attribute for this called
aria-activedescendant. This attribute is placed on the combobox element. The attribute value is the ID of the currently active (pseudo-focussed) option.
To make all of this easier, we recommend using a plugin such as jquery-active-descendant. After your HTML structure is in place, simply activate the plugin on the widget and up/down arrow keys will update the necessary states. Use CSS to style the active descendant in any way you like.
JAWS Keyboard Navigation
At the time of writing we have found that role of combobox does not force JAWS into application mode. This means that ARROW keys will be intercepted by JAWS, thus making UP/DOWN arrow key navigation problematic. In order to force JAWS into application mode, we apply a wrapper element with
<span role="application"> <span class="combobox" id="combobox-0"> <!-- label, input, description, etc --> </span> </span>
We hope that this workaround will only be a temporary measure until we see better support for combobox role in JAWS.
We expect to have this section finalised in 2016.
This section gives an overview of ARIA usage, within the context of this pattern.
We have found that this wrapper role is necessary for correct behaviour of keyboard accessibility in JAWS and IE.
This attribute changes the role of the text input from
This role converts the offscreen text description/instructions into an ARIA live region.
The list of suggestions has a role of listbox
Each listbox item has a role of option.
This property connects the combobox to the offscreen description/instructions.
This property connects the combobox to the listbox.
Conveys the expanded state of the combobox.
Provides the expand/collapse button with an accessible label, in the case where it has no visible text (i.e. an icon button).