Read Me First
No ARIA is better than Bad ARIA
Functionally, ARIA roles, states, and properties are analogous to a CSS for assistive technologies.
For screen reader users, ARIA controls the rendering of their non-visual experience.
Incorrect ARIA misrepresents visual experiences, with potentially devastating effects on their corresponding non-visual experiences.
Before using ARIA or any of the guidance in this document, please take time to understand the following two essential principles.
Principle 1: A role is a promise
This code:
<div role="button">Place Order</div>
Is a promise that the author of that <div>
has also incorporated JavaScript that provides the keyboard interactions expected for a button.
Unlike HTML input elements, ARIA roles do not cause browsers to provide keyboard behaviors or styling.
Using a role without fulfilling the promise of that role is similar to making a "Place Order" button that abandons an order and empties the shopping cart.
One of the objectives of this guide is to define expected behaviors for each ARIA role.
Principle 2: ARIA Can Both Cloak and Enhance, Creating Both Power and Danger
The information assistive technologies need about the meaning and purpose of user interface elements is called accessibility semantics.
From the perspective of assistive technologies, ARIA gives authors the ability to dress up HTML and SVG elements with critical accessibility semantics that the assistive technologies would not otherwise be able to reliably derive.
Some of ARIA is like a cloak; it covers up, or overrides, the original semantics or content.
<a role="menuitem">Assistive tech users perceive this element as an item in a menu, not a link.</a>
<a aria-label="Assistive tech users can only perceive the contents of this aria-label, not the link text">Link Text</a>
On the other hand, some uses of ARIA are more like suspenders or belts; they add meaning that provides essential support to the original content.
<button aria-pressed="false">Mute</button>
This is the power of ARIA.
It enables authors to describe nearly any user interface component in ways that assistive technologies can reliably interpret, thus making components accessible to assistive technology users.
This is also the danger of ARIA.
Authors can inadvertently override accessibility semantics.
<table role="log">
<!--
Table that assistive technology users will not perceive as a table.
The log role tells browser this is a log, not a table.
-->
</table>
<ul role="navigation">
<!-- This is a navigation region, not a list. -->
<li><a href="uri1">nav link 1</li>
<li><a href="uri2">nav link 2</li>
<!-- ERROR! Previous list items are not in a list! -->
</ul>
Browser and Assistive Technology Support
Testing assistive technology interoperability is essential before using code from this guide in production.
Because the purpose of this guide is to illustrate appropriate use of ARIA 1.1 as defined in the ARIA specification, the design patterns, reference examples, and sample code intentionally do not describe and implement coding techniques for working around problems caused by gaps in support for ARIA 1.1 in browsers and assistive technologies.
It is thus advisable to test implementations thoroughly with each browser and assistive technology combination that is relevant within a target audience.
Similarly, JavaScript and CSS in this guide is written to be compatible with the most recent version of Chrome, Firefox, Internet Explorer, and Safari at the time of writing.
In particular, some JavaScript and CSS may not function correctly in Internet Explorer version 10 or earlier.
Except in cases where the ARIA Working Group and other contributors have overlooked an error,
examples in this guide that do not function well in a particular browser or with a specific assistive technology are demonstrating browser or assistive technology bugs.
Browser and assistive technology developers can thus utilize code in this guide to help assess the quality of their support for ARIA 1.1.
Mobile and Touch Support
Currently, this guide does not indicate which examples are compatible with mobile browsers or touch interfaces.
While some of the examples include specific features that enhance mobile and touch support, some ARIA features are not supported in any mobile browser.
In addition, there is not yet a standardized approach for providing touch interactions that work across mobile browsers.
More guidance about touch and mobile support is planned for future releases of the guide.
Design Patterns and Widgets
This section demonstrates how to make common rich internet application patterns and widgets accessible by applying WAI-ARIA roles, states, and properties and implementing keyboard support.
Combo Box
A combobox is a widget made up of the combination of two distinct elements:
1) a single-line textbox, and 2) an associated pop-up element for helping users set the value of the textbox.
The popup may be a listbox,
grid,
tree, or
dialog.
Many implementations also include a third optional element -- a graphical button adjacent to the textbox, indicating the availability of the popup.
Activating the button displays the popup if suggestions are available.
The popup is hidden by default, and the conditions that trigger its display are specific to each implementation. Some possible popup display conditions include:
- It is displayed only if a certain number of characters are typed in the textbox and those characters match some portion of one of the suggested values.
- It is displayed as soon as the textbox is focused, even if the textbox is empty.
- It is displayed when the Down Arrow key is pressed or the
show
button is activated, possibly with a dependency on the content of the textbox.
- It is displayed if the value of the textbox is altered in a way that creates one or more partial matches to a suggested value.
Combobox widgets are useful for setting the value of a single-line textbox in one of two types of scenarios:
-
The value for the textbox must be chosen from a predefined set of allowed values,
e.g., a location field must contain a valid location name.
Note that the listbox and menu button patterns are also useful in this scenario; differences between combobox and alternative patterns are described below.
-
The textbox may contain any arbitrary value, but it is advantageous to suggest possible values to the user,
e.g., a search field may suggest similar or previous searches to save the user time.
The nature of the suggested values and the way the suggestions are presented is called the autocomplete behavior.
Comboboxes can have one of four forms of autocomplete:
-
No autocomplete: When the popup is triggered, the suggested values it contains are the same regardless of the characters typed in the textbox.
For example, the popup suggests a set of recently entered values, and the suggestions do not change as the user types.
-
List autocomplete with manual selection: When the popup is triggered, it presents suggested values that complete or logically correspond to the characters typed in the textbox.
The character string the user has typed will become the value of the textbox unless the user selects a value in the popup.
-
List autocomplete with automatic selection: When the popup is triggered, it presents suggested values that complete or logically correspond to the characters typed in the textbox,
and the first suggestion is automatically highlighted as selected.
The automatically selected suggestion becomes the value of the textbox when the combobox loses focus unless the user chooses a different suggestion or changes the character string in the textbox.
-
List with inline autocomplete: This is the same as list with automatic selection with one additional feature.
The portion of the selected suggestion that has not been typed by the user, a completion string, appears inline after the input cursor in the textbox.
The inline completion string is visually highlighted and has a selected state.
With any form of list autocomplete, the popup may appear and disappear as the user types.
For example, if the user types a two character string that triggers five suggestions to be displayed but then types a third character that forms a string that does not have any matching suggestions,
the popup may close and, if present, the inline completion string disappears.
When constructing a widget that is both visually compact and enables users to choose one value from a set of discrete values, often either a listbox or menu button is simpler to implement and use.
One feature of combobox that distinguishes it from both listbox and menu button is that the value of the combobox is presented in an edit field.
Thus, the combobox gives users one function that both listbox and menu button lack, namely the ability to select some or all of the value for copying to the clipboard.
One feature that distinguishes both combobox and menu button widgets from listbox widgets is their ability to provide an undo mechanism.
In many implementations, users can navigate the set of allowed values in a combobox or menu and then decide to revert to the value the widget had before navigating by pressing escape.
In contrast, navigating a listbox immediately changes its value, and escape does not provide an undo mechanism.
The options for a combobox to popup a grid, tree, or dialog were introduced in ARIA 1.1.
Changes made in the ARIA 1.1 specification also add support for a code pattern that enables assistive technologies to present the textbox and popup as separately perceivable elements.
both ARIA 1.0 and 1.1 patterns are described in the following sections.
While using the ARIA 1.1 pattern is recommended as soon as assistive technology support is sufficient,
there are no plans to deprecate the ARIA 1.0 pattern.
Keyboard Interaction
- Tab: The textbox is in the page Tab sequence.
- Note: The popup indicator icon or button (if present), the popup, and the popup descendants are excluded from the page Tab sequence.
Textbox Keyboard Interaction
When focus is in the textbox:
- Down Arrow: If the popup is available, moves focus into the popup:
- If the autocomplete behavior automatically selected a suggestion before Down Arrow was pressed, focus is placed on the suggestion following the automatically selected suggestion.
- Otherwise, places focus on the first focusable element in the popup.
- Up Arrow (Optional): If the popup is available, places focus on the last focusable element in the popup.
- Escape: Dismisses the popup if it is visible. Optionally, clears the textbox.
-
Enter: If an autocomplete suggestion is automatically selected, accepts the suggestion either by placing the input cursor at the end of the accepted value in the textbox or by performing a default action on the value.
For example, in a messaging application, the default action may be to add the accepted value to a list of message recipients and then clear the textbox so the user can add another recipient.
- Printable Characters: Type characters in the textbox. Note that some implementations may regard certain characters as invalid and prevent their input.
- Standard single line text editing keys appropriate for the device platform (see note below).
- Alt + Down Arrow (Optional): If the popup is available but not displayed, displays the popup without moving focus.
- Alt + Up Arrow (Optional): If the popup is displayed:
- If the popup contains focus, returns focus to the textbox.
- Closes the popup.
Standard single line text editing keys appropriate for the device platform:
- include keys for input, cursor movement, selection, and text manipulation.
- Standard key assignments for editing functions depend on the device operating system.
- The most robust approach for providing text editing functions is to rely on browsers, which supply them for HTML inputs with type text and for elements with the
contenteditable
HTML attribute.
- IMPORTANT: Be sure that JavaScript does not interfere with browser-provided text editing functions by capturing key events for the keys used to perform them.
Listbox Popup Keyboard Interaction
When focus is in a listbox popup:
- Enter: Accepts the focused option in the listbox by closing the popup and placing the accepted value in the textbox with the input cursor at the end of the value.
- Escape: Closes the popup and returns focus to the textbox. Optionally, clears the contents of the textbox.
-
Right Arrow: Returns focus to the textbox without closing the popup and moves the input cursor one character to the right.
If the input cursor is on the right-most character, the cursor does not move.
-
Left Arrow: Returns focus to the textbox without closing the popup and moves the input cursor one character to the left.
If the input cursor is on the left-most character, the cursor does not move.
- Any printable character: Returns the focus to the textbox without closing the popup and types the character.
- Backspace (Optional): Returns focus to the textbox and deletes the character prior to the cursor.
- Delete (Optional): Returns focus to the textbox, removes the selected state if a suggestion was selected, and removes the inline autocomplete string if present.
- Down Arrow: Moves focus to and selects the next option. If focus is on the last option, either returns focus to the textbox or does nothing.
- Up Arrow: Moves focus to and selects the previous option. If focus is on the first option, either returns focus to the textbox or does nothing.
- Home (Optional): Either moves focus to and selects the first option or returns focus to the textbox and places the cursor on the first character.
- End (Optional): Either moves focus to the last option or returns focus to the textbox and places the cursor after the last character.
- DOM Focus is maintained on the combobox textbox and the assistive technology focus is moved within the listbox using
aria-activedescendant
as described in Managing Focus in Composites Using aria-activedescendant.
- Selection follows focus in the listbox; the listbox allows only one suggested value to be selected at a time for the textbox value.
Grid Popup Keyboard Interaction
In a grid popup, each suggested value may be represented by either a single cell or an entire row.
See notes below for how this aspect of grid design effects the keyboard interaction design and the way that selection moves in response to focus movements.
- Enter: Accepts the currently selected suggested value by closing the popup and placing the selected value in the textbox with the input cursor at the end of the value.
- Escape: Closes the popup and returns focus to the textbox. Optionally, clears the contents of the textbox.
- Any printable character: Returns the focus to the textbox without closing the popup and types the character.
- Backspace (Optional): Returns focus to the textbox and deletes the character prior to the cursor.
- Delete (Optional): Returns focus to the textbox, removes the selected state if a suggestion was selected, and removes the inline autocomplete string if present.
-
Right Arrow: Moves focus one cell to the right.
Optionally, if focus is on the right-most cell in the row, focus may move to the first cell in the following row.
If focus is on the last cell in the grid, either does nothing or returns focus to the textbox.
-
Left Arrow: Moves focus one cell to the left.
Optionally, if focus is on the left-most cell in the row, focus may move to the last cell in the previous row.
If focus is on the first cell in the grid, either does nothing or returns focus to the textbox.
-
Down Arrow: Moves focus one cell down.
If focus is in the last row of the grid, either does nothing or returns focus to the textbox.
-
Up Arrow: Moves focus one cell up.
If focus is in the first row of the grid, either does nothing or returns focus to the textbox.
-
Page Down (Optional): Moves focus down an author-determined number of rows, typically scrolling so the bottom row in the currently visible set of rows becomes one of the first visible rows.
If focus is in the last row of the grid, focus does not move.
-
Page Up (Optional): Moves focus up an author-determined number of rows, typically scrolling so the top row in the currently visible set of rows becomes one of the last visible rows.
If focus is in the first row of the grid, focus does not move.
- Home (Optional): Either:
- Moves focus to the first cell in the row that contains focus. Or, if the grid has fewer than three cells per row or multiple suggested values per row, focus may move to the first cell in the grid.
- Returns focus to the textbox and places the cursor on the first character.
- End (Optional): Either:
- Moves focus to the last cell in the row that contains focus. Or, if the grid has fewer than three cells per row or multiple suggested values per row, focus may move to the last cell in the grid.
- Returns focus to the textbox and places the cursor after the last character.
- Control + Home (optional): moves focus to the first row.
- Control + End (Optional): moves focus to the last row.
- DOM Focus is maintained on the combobox textbox and the assistive technology focus is moved within the grid using
aria-activedescendant
as described in Managing Focus in Composites Using aria-activedescendant.
- The grid allows only one suggested value to be selected at a time for the textbox value.
- In a grid popup, each suggested value may be represented by either a single cell or an entire row. This aspect of design effects focus and selection movement:
- If every cell contains a different suggested value:
- Selection follows focus so that the cell containing focus is selected.
- Horizontal arrow key navigation typically wraps from one row to another.
- Vertical arrow key navigation typically wraps from one column to another.
- If all cells in a row contain information about the same suggested value:
- Either the row containing focus is selected or a cell containing a suggested value is selected when any cell in the same row contains focus.
- Horizontal key navigation may wrap from one row to another.
- Vertical arrow key navigation does not wrap from one column to another.
Tree Popup Keyboard Interaction
In some implementations of tree popups, some or all parent nodes may serve as suggestion category labels so may not be selectable values.
See notes below for how this aspect of the design effects the way selection moves in response to focus movements.
When focus is in a vertically oriented tree popup:
- Enter: Accepts the currently selected suggested value by closing the popup and placing the selected value in the textbox with the input cursor at the end of the value.
- Escape: Closes the popup and returns focus to the textbox. Optionally, clears the contents of the textbox.
- Any printable character: Returns the focus to the textbox without closing the popup and types the character.
- Right arrow:
- When focus is on a closed node, opens the node; focus and selection do not move.
- When focus is on a open node, moves focus to the first child node and selects it if it is selectable.
- When focus is on an end node, does nothing.
- Left arrow:
- When focus is on an open node, closes the node.
- When focus is on a child node that is also either an end node or a closed node, moves focus to its parent node and selects it if it is selectable.
- When focus is on a root node that is also either an end node or a closed node, does nothing.
- Down Arrow: Moves focus to the next node that is focusable without opening or closing a node and selects it if it is selectable.
- Up Arrow: Moves focus to the previous node that is focusable without opening or closing a node and selects it if it is selectable.
- Home: Moves focus to the first node in the tree without opening or closing a node and selects it if it is selectable.
- End: Moves focus to the last node in the tree that is focusable without opening a node and selects it if it is selectable.
- DOM Focus is maintained on the combobox textbox and the assistive technology focus is moved within the tree using
aria-activedescendant
as described in Managing Focus in Composites Using aria-activedescendant.
- The tree allows only one suggested value to be selected at a time for the textbox value.
-
In a tree popup, some or all parent nodes may not be selectable values; they may serve as category labels for suggested values.
If focus moves to a node that is not a selectable value, either:
- The previously selected node, if any, remains selected until focus moves to a node that is selectable.
- There is no selected value.
- In either case, focus is visually distinct from selection so users can readily see if a value is selected or not.
- If the nodes in a tree are arranged horizontally:
- Down Arrow performs as Right Arrow is described above, and vice versa.
- Up Arrow performs as Left Arrow is described above, and vice versa.
Dialog Popup Keyboard Interaction
When focus is in a dialog popup:
- There are two ways to close the popup and return focus to the textbox:
- Perform an action in the dialog, such as activate a button, that specifies a value for the textbox.
-
Cancel out of the dialog, e.g., press Escape or activate the cancel button in the dialog.
Canceling either returns focus to the text box without changing the textbox value or returns focus to the textbox and clears the textbox.
- The dialog implements the keyboard interaction defined in the modal dialog pattern.
Unlike other combobox popups, dialogs do not support aria-activedescendant
so DOM focus moves into the dialog from the textbox.
WAI-ARIA Roles, States, and Properties
The role, state, and property guidance where the ARIA 1.1 and ARIA 1.0 patterns differ is listed first.
The subsequent guidance applies to both patterns.
- In a combobox implementing the ARIA 1.1 pattern:
- The element that serves as the combobox container has role combobox.
- The element with role
combobox
contains or owns a textbox element that has either role textbox or role searchbox.
- When the combobox popup is visible, the combobox element contains or owns an element that has role listbox, tree, grid, or dialog.
-
If the combobox popup has a role other than
listbox
, the element with role combobox
has aria-haspopup set to a value that corresponds to the popup type.
That is, aria-haspopup
is set to grid
, tree
, or dialog
.
Note that elements with role combobox
have an implicit aria-haspopup
value of listbox
.
- When the combobox popup is visible, the textbox element has aria-controls set to a value that refers to the combobox popup element.
- In a combobox implementing the ARIA 1.0 pattern:
- The element that serves as the textbox has role combobox.
- When the combobox popup is visible, the element with role combobox has aria-owns set to a value that refers to an element with role listbox.
-
the element with role
combobox
has a value for aria-haspopup of listbox
.
Note that elements with role combobox
have an implicit aria-haspopup
value of listbox
.
-
The textbox element has a value for aria-multiline of
false
.
Note that the default value of aria-multiline
is false
.
-
When the combobox popup is not visible, the element with role
combobox
has aria-expanded set to false
.
When the popup element is visible, aria-expanded
is set to true
.
Note that elements with role combobox
have a default value for aria-expanded
of false
.
- When a combobox receives focus, DOM focus is placed on the textbox element.
- When a descendant of a listbox, grid, or tree popup is focused, DOM focus remains on the textbox and the textbox has aria-activedescendant set to a value that refers to the focused element within the popup.
- In a combobox with a listbox, grid, or tree popup, when a suggested value is visually indicated as the currently selected value, the
option
, gridcell
, row
, or treeitem
containing that value has aria-selected set to true
.
-
If the combobox has a visible label, the element with role combobox has aria-labelledby set to a value that refers to the labeling element.
Otherwise, the combobox element has a label provided by aria-label.
- The textbox element has aria-autocomplete set to a value that corresponds to its autocomplete behavior:
none
: When the popup is displayed, the suggested values it contains are the same regardless of the characters typed in the textbox.
list
: When the popup is triggered, it presents suggested values that complete or logically correspond to the characters typed in the textbox.
-
both
: When the popup is triggered, it presents suggested values that complete or logically correspond to the characters typed in the textbox.
In addition, the portion of the selected suggestion that has not been typed by the user, known as the completion string
, appears inline after the input cursor in the textbox.
The inline completion string is visually highlighted and has a selected state.
- When referring to the roles, states, and properties documentation for the below list of patterns used for popups, keep in mind that a combobox is a single-select widget where selection always follows focus in the popup.
- The roles, states, and properties for popup elements are defined in their respective design patterns:
Feed
A feed is a section of a page that automatically loads new sections of content as the user scrolls.
The sections of content in a feed are presented in article elements.
So, a feed can be thought of as a dynamic list of articles that often appears to scroll infinitely.
The feature that most distinguishes feed from other ARIA patterns that support loading data as users scroll, e.g., a grid, is that a feed is a structure, not a widget.
Consequently, assistive technologies with a reading mode, such as screen readers, default to reading mode when interacting with feed content.
However, unlike most other WAI-ARIA structures, a feed establishes an interoperability contract between the web page and assistive technologies.
The contract governs scroll interactions so that assistive technology users can read articles, jump forward and backward by article, and reliably trigger new articles to load while in reading mode.
For example, a product page on a shopping site may have a related products section that displays five products at a time.
As the user scrolls, more products are requested and loaded into the DOM.
While a static design might include a next button for loading five more products, a dynamic implementation that automatically loads more data as the user scrolls simplifies the user experience and reduces the inertia associated with viewing more than the first five product suggestions.
But, unfortunately when web pages load content dynamically based on scroll events, it can cause usability and interoperability difficulties for users of assistive technologies.
The feed pattern enables reliable assistive technology reading mode interaction by establishing the following interoperability agreement between the web page and assistive technologies:
- In the context of a feed, the web page code is responsible for:
-
Appropriate visual scrolling of the content based on which article contains DOM focus.
- Loading or removing feed articles based on which article contains DOM focus.
- In the context of a feed, assistive technologies with a reading mode are responsible for:
- Indicating which article contains the reading cursor by ensuring the article element or one of its descendants has DOM focus.
- providing reading mode keys that move DOM focus to the next and previous articles.
- Providing reading mode keys for moving the reading cursor and DOM focus past the end and before the start of the feed.
Thus, implementing the feed pattern allows a screen reader to reliably read and trigger the loading of feed content while staying in its reading mode.
Another feature of the feed pattern is its ability to facilitate skim reading for assistive technology users.
Web page authors may provide both an accessible name and description for each article.
By identifying the elements inside of an article that provide the title and the primary content, assistive technologies can provide functions that enable users to jump from article to article and efficiently discern which articles may be worthy of more attention.
Keyboard Interaction
The feed pattern is not based on a desktop GUI widget so the feed
role is not associated with any well-established keyboard conventions.
Supporting the following, or a similar, interface is recommended.
When focus is inside the feed:
- Page Down: Move focus to next article.
- Page Up: Move focus to previous article.
- Control + End: Move focus to the first focusable element after the feed.
- Control + Home: Move focus to the first focusable element before the feed.
- Due to the lack of convention, providing easily discoverable keyboard interface documentation is especially important.
-
In some cases, a feed may contain a nested feed.
For example, an article in a social media feed may contain a feed of comments on that article.
To navigate the nested feed, users first move focus inside the nested feed.
Options for supporting nested feed navigation include:
-
Users move focus into the nested feed from the content of the containing article with Tab.
This may be slow if the article contains a significant number of links, buttons, or other widgets.
- Provide a key for moving focus from the elements in the containing article to the first item in the nested feed, e.g., Alt + Page Down.
- To continue reading the outer feed, Control + End moves focus to the next article in the outer feed.
- In the rare circumstance that a feed article contains a widget that uses the above suggested keys, the feed navigation key will operate the contained widget, and the user needs to move focus to an element that does not utilize the feed navigation keys in order to navigate the feed.
WAI-ARIA Roles, States, and Properties
- The element that contains the set of feed articles has role feed.
-
If the feed has a visible title, the
feed
element has aria-labelledby referring to the element containing the title.
Otherwise, the feed
element has a label specified with aria-label.
-
Each unit of content in a feed is contained in an element with role article.
All content inside the feed is contained in an
article
element.
-
Each
article
element has
aria-labelledby
referring to elements inside the article that can serve as a distinguishing label.
-
It is optional but strongly recommended for each
article
element to have
aria-describedby
referring to one or more elements inside the article that serve as the primary content of the article.
-
Each
article
element has
aria-posinset
set to a value that represents its position in the feed.
-
Each
article
element has
aria-setsize
set to a value that represents either the total number of articles that have been loaded or the total number in the feed,
depending on which value is deemed more helpful to users.
If the total number in the feed is undetermined, it can be represented by a aria-setsize
value of -1
.
-
When
article
elements are being added to or removed from the feed
container,
and if the operation requires multiple DOM operations,
the feed
element has
aria-busy
set to true
during the update operation.
Note that it is extremely important that aria-busy
is set to false
when the operation is complete or the changes may not become visible to some assistive technology users.
Grids : Interactive Tabular Data and Layout Containers
A grid widget is a container that enables users to navigate the information or interactive elements it contains using directional navigation keys, such as arrow keys, Home , and End.
As a generic container widget that offers flexible keyboard navigation, it can serve a wide variety of needs.
It can be used for purposes as simple as grouping a collection of checkboxes or navigation links or as complex as creating a full-featured spreadsheet application.
While the words "row" and "column" are used in the names of WAI-ARIA attributes and by assistive technologies when describing and presenting the logical structure of elements with the grid
role, using the grid
role on an element does not necessarily imply that its visual presentation is tabular.
When presenting content that is tabular, consider the following factors when choosing between implementing this grid
pattern or the table pattern.
-
A
grid
is a composite widget so it:
- Always contains multiple focusable elements.
- Only one of the focusable elements contained by the grid is included in the page tab sequence.
- Requires the author to provide code that manages focus movement inside it.
- All focusable elements contained in a table are included in the page tab sequence.
Uses of the grid
pattern broadly fall into two categories: presenting tabular information (data grids) and grouping other widgets (layout grids).
Even though both data grids and layout grids employ the same ARIA roles, states, and properties, differences in their content and purpose surface factors that are important to consider in keyboard interaction design.
To address these factors, the following two sections describe separate keyboard interaction patterns for data and layout grids.
Examples
- Layout Grid Examples: Three example implementations of grids that are used to lay out widgets, including a collection of navigation links, a message recipients list, and a set of search results.
- Data Grid Examples: Three example implementations of grid that include features relevant to presenting tabular information, such as content editing, sort, and column hiding.
- Advanced Data Grid Example: Example of a grid with behaviors and features similar to a typical spreadsheet, including cell and row selection.
Data Grids For Presenting Tabular Information
A grid
can be used to present tabular information that has column titles, row titles, or both.
The grid
pattern is particularly useful if the tabular information is editable or interactive.
For example, when data elements are links to more information, rather than presenting them in a static table and including the links in the tab sequence, implementing the grid
pattern provides users with intuitive and efficient keyboard navigation of the grid contents as well as a shorter tab sequence for the page.
A grid
may also offer functions, such as cell content editing, selection, cut, copy, and paste.
In a grid, every cell contains a focusable element or is itself focusable, regardless of whether the cell content is editable or interactive.
There is one exception: if column or row header cells do not provide functions, such as sort or filter, they do not need to be focusable.
One reason it is important for all cells to be able to receive or contain keyboard focus is that screen readers will typically be in their application reading mode, rather than their document reading mode, when users are interacting with the grid.
While in application mode, a screen reader user hears only focusable elements and content that labels focusable elements.
So, screen reader users may unknowingly overlook elements contained in a grid that are either not focusable or not used to label a column or row.
Keyboard Interaction For Data Grids
The following keys provide grid navigation by moving focus among cells of the grid.
Implementations of grid make these key commands available when an element in the grid has received focus, e.g., after a user has moved focus to the grid with Tab.
-
Right Arrow: Moves focus one cell to the right.
If focus is on the right-most cell in the row, focus does not move.
- Left Arrow: Moves focus one cell to the left. If focus is on the left-most cell in the row, focus does not move.
- Down Arrow: Moves focus one cell down. If focus is on the bottom cell in the column, focus does not move.
- Up Arrow: Moves focus one cell Up. If focus is on the top cell in the column, focus does not move.
- Page Down: Moves focus down an author-determined number of rows, typically scrolling so the bottom row in the currently visible set of rows becomes one of the first visible rows. If focus is in the last row of the grid, focus does not move.
- Page Up: Moves focus up an author-determined number of rows, typically scrolling so the top row in the currently visible set of rows becomes one of the last visible rows. If focus is in the first row of the grid, focus does not move.
- Home: moves focus to the first cell in the row that contains focus.
- End: moves focus to the last cell in the row that contains focus.
- Control + Home: moves focus to the first cell in the first row.
- Control + End: moves focus to the last cell in the last row.
-
When the above grid navigation keys move focus, whether the focus is set on an element inside the cell or the grid cell depends on cell content.
See Whether to Focus on a Cell or an Element Inside It.
-
While navigation keys, such as arrow keys, are moving focus from cell to cell, they are not available to do something like operate a combobox or move an editing caret inside of a cell.
If this functionality is needed, see Editing and Navigating Inside a Cell.
- If navigation functions can dynamically add more rows or columns to the DOM, key events that move focus to the beginning or end of the grid, such as control + End, may move focus to the last row in the DOM rather than the last available row in the back-end data.
If a grid supports selection of cells, rows, or columns, the following keys are commonly used for these functions.
- Control + Space: selects the column that contains the focus.
- Shift + Space: Selects the row that contains the focus. If the grid includes a column with checkboxes for selecting rows, this key can serve as a shortcut for checking the box when focus is not on the checkbox.
- Control + A: Selects all cells.
- Shift + Right Arrow: Extends selection one cell to the right.
- Shift + Left Arrow: Extends selection one cell to the left.
- Shift + Down Arrow: Extends selection one cell down.
- Shift + Up Arrow: Extends selection one cell Up.
See for cut, copy, and paste key assignments.
Layout Grids for Grouping Widgets
The grid
pattern can be used to group a set of interactive elements, such as links, buttons, or checkboxes.
Since only one element in the entire grid is included in the tab sequence, grouping with a grid can dramatically reduce the number of tab stops on a page.
This is especially valuable if scrolling through a list of elements dynamically loads more of those elements from a large data set, such as in a continuous list of suggested products on a shopping site.
If elements in a list like this were in the tab sequence, keyboard users are effectively trapped in the list.
If any elements in the group also have associated elements that appear on hover, the grid
pattern is also useful for providing keyboard access to those contextual elements of the user interface.
Unlike grids used to present data, A grid
used for layout does not necessarily have header cells for labeling rows or columns and might contain only a single row or a single column.
Even if it has multiple rows and columns, it may present a single, logically homogenous set of elements.
For example, a list of recipients for a message may be a grid where each cell contains a link that represents a recipient.
The grid may initially have a single row but then wrap into multiple rows as recipients are added.
In such circumstances, grid navigation keys may also wrap so the user can read the list from beginning to end by pressing either Right Arrow or Down Arrow.
While This type of focus movement wrapping can be very helpful in a layout grid, it would be disorienting if used in a data grid, especially for users of assistive technologies.
Because arrow keys are used to move focus inside of a grid
, a grid
is both easier to build and use if the components it contains do not require the arrow keys to operate. If a cell contains an element like a listbox, then an extra key command to focus and activate the listbox is needed as well as a command for restoring the grid navigation functionality. Approaches to supporting this need are described in the section on Editing and Navigating Inside a Cell.
Keyboard Interaction For Layout Grids
The following keys provide grid navigation by moving focus among cells of the grid.
Implementations of grid make these key commands available when an element in the grid has received focus, e.g., after a user has moved focus to the grid with Tab.
-
Right Arrow: Moves focus one cell to the right.
Optionally, if focus is on the right-most cell in the row, focus may move to the first cell in the following row.
If focus is on the last cell in the grid, focus does not move.
-
Left Arrow: Moves focus one cell to the left.
Optionally, if focus is on the left-most cell in the row, focus may move to the last cell in the previous row.
If focus is on the first cell in the grid, focus does not move.
-
Down Arrow: Moves focus one cell down.
Optionally, if focus is on the bottom cell in the column, focus may move to the top cell in the following column.
If focus is on the last cell in the grid, focus does not move.
-
Up Arrow: Moves focus one cell up.
Optionally, if focus is on the top cell in the column, focus may move to the bottom cell in the previous column.
If focus is on the first cell in the grid, focus does not move.
-
Page Down (Optional): Moves focus down an author-determined number of rows, typically scrolling so the bottom row in the currently visible set of rows becomes one of the first visible rows.
If focus is in the last row of the grid, focus does not move.
-
Page Up (Optional): Moves focus up an author-determined number of rows, typically scrolling so the top row in the currently visible set of rows becomes one of the last visible rows.
If focus is in the first row of the grid, focus does not move.
-
Home: moves focus to the first cell in the row that contains focus.
Optionally, if the grid has a single column or fewer than three cells per row, focus may instead move to the first cell in the grid.
-
End: moves focus to the last cell in the row that contains focus.
Optionally, if the grid has a single column or fewer than three cells per row, focus may instead move to the last cell in the grid.
- Control + Home (optional): moves focus to the first cell in the first row.
- Control + End (Optional): moves focus to the last cell in the last row.
-
When the above grid navigation keys move focus, whether the focus is set on an element inside the cell or the grid cell depends on cell content.
See Whether to Focus on a Cell or an Element Inside It.
-
While navigation keys, such as arrow keys, are moving focus from cell to cell, they are not available to do something like operate a combobox or move an editing caret inside of a cell.
If this functionality is needed, see Editing and Navigating Inside a Cell.
- If navigation functions can dynamically add more rows or columns to the DOM, key events that move focus to the beginning or end of the grid, such as control + End, may move focus to the last row in the DOM rather than the last available row in the back-end data.
It would be unusual for a layout grid to provide functions that require cell selection. If it did, though, the following keys are commonly used for these functions.
- Control + Space: selects the column that contains the focus.
-
Shift + Space: Selects the row that contains the focus.
If the grid includes a column with checkboxes for selecting rows, this key can serve as a shortcut for checking the box when focus is not on the checkbox.
- Control + A: Selects all cells.
- Shift + Right Arrow: Extends selection one cell to the right.
- Shift + Left Arrow: Extends selection one cell to the left.
- Shift + Down Arrow: Extends selection one cell down.
- Shift + Up Arrow: Extends selection one cell Up.
See for cut, copy, and paste key assignments.
Keyboard Interaction - Setting Focus and Navigating Inside Cells
This section describes two important aspects of keyboard interaction design shared by both data and layout grid patterns:
- Choosing whether a cell or an element inside a cell receives focus in response to grid navigation key events.
- Enabling grid navigation keys to be used to interact with elements inside of a cell.
Whether to Focus on a Cell Or an Element Inside It
For assistive technology users, the quality of experience when navigating a grid heavily depends on both what a cell contains and on where keyboard focus is set.
For example, if a cell contains a button and a grid navigation key places focus on the cell instead of the button, screen readers announce the button label but do not tell users a button is present.
There are two optimal cell design and focus behavior combinations:
-
A cell contains one widget whose operation does not require arrow keys and grid navigation keys set focus on that widget.
Examples of such widgets include link, button, menubutton, toggle button, radio button (not radio group), switch, and checkbox.
- A cell contains text or a single graphic and grid navigation keys set focus on the cell.
While any combination of widgets, text, and graphics may be included in a single cell, grids that do not follow one of these two cell design and focus movement patterns add complexity for authors or users or both.
The reference implementations included in the example section below demonstrate some strategies for making other cell designs as accessible as possible, but the most widely accessible experiences are likely to come by applying the above two patterns.
Editing and Navigating Inside a Cell
While navigation keys, such as arrow keys, are moving focus from cell to cell, they are not available to perform actions like operate a combobox or move an editing caret inside of a cell. The user may need keys that are used for grid navigation to operate
elements inside a cell if a cell contains:
- Editable content.
- Multiple widgets.
- A widget that utilizes arrow keys in its interaction model, such as a radio group or slider.
Following are common keyboard conventions for disabling and restoring grid navigation functions.
-
Enter: Disables grid navigation and:
- If the cell contains editable content, places focus in an input field, such as a textbox. If the input is a single-line text field, a subsequent press of Enter may either restore grid navigation
functions or move focus to an input field in a neighboring cell.
- If the cell contains one or more widgets, places focus on the first widget.
-
F2:
- If the cell contains editable content, places focus in an input field, such as a textbox. A subsequent press of F2 restores grid navigation functions.
- If the cell contains one or more widgets, places focus on the first widget. A subsequent press of F2 restores grid navigation functions.
- Alphanumeric keys: If the cell contains editable content, places focus in an input field, such as a textbox.
When grid navigation is disabled, conventional changes to navigation behaviors include:
- Escape: restores grid navigation. If content was being edited, it may also undo edits.
-
Right Arrow or Down Arrow: If the cell contains multiple widgets, moves focus to the next widget inside the cell, optionally wrapping to the first widget if focus is on the last widget.
Otherwise, passes the key event to the focused widget.
-
Left Arrow or Up Arrow: If the cell contains multiple widgets, moves focus to the previous widget inside the cell, optionally wrapping to the first widget if focus is on the last widget.
Otherwise, passes the key event to the focused widget.
-
Tab: moves focus to the next widget in the grid.
Optionally, the focus movement may wrap inside a single cell or within the grid itself.
-
Shift + Tab: moves focus to the previous widget in the grid.
Optionally, the focus movement may wrap inside a single cell or within the grid itself.
WAI-ARIA Roles, States, and Properties
- The grid container has role grid.
- Each row container has role row and is either a DOM descendant of or owned by the
grid
element or an element with role rowgroup.
- Each cell is either a DOM descendant of or owned by a
row
element and has one of the following roles:
- columnheader if the cell contains a title or header information for the column.
- rowheader if the cell contains title or header information for the row.
- gridcell if the cell does not contain column or row header information.
-
If there is an element in the user interface that serves as a label for the grid, aria-labelledby is set on the grid element with a value that refers to the labeling element.
Otherwise, a label is specified for the grid element using aria-label.
- If the grid has a caption or description, aria-describedby is set on the grid element with a value referring to the element containing the description.
- If the grid provides sort functions, aria-sort is set to an appropriate value on the header cell element for the sorted column or row as described in the section on grid and table properties.
-
If the grid supports selection, when a cell or row is selected, the selected element has aria-selected set
true
.
If the grid supports column selection and a column is selected, all cells in the column have aria-selected
set to true
.
-
If the grid provides content editing functionality and contains cells that may have edit capabilities disabled in certain conditions, aria-readonly may be set
true
on cells where editing is disabled.
If edit functions are disabled for all cells, aria-readonly
may be set true
on the grid element.
Grids that do not provide editing functions do not include the aria-readonly
attribute on any of their elements.
-
If there are conditions where some rows or columns are hidden or not present in the DOM, e.g., data is dynamically loaded when scrolling or the grid provides functions for hiding rows or columns, the following properties are applied as described in the section on grid and table properties.
- If the grid includes cells that span multiple rows or multiple columns, and if the
grid
role is NOT applied to an HTML table
element, then aria-rowspan or aria-colspan is applied as described in grid and table properties.
-
If the element with the
grid
role is an HTML table
element, then it is not necessary to use ARIA roles for rows and cells because the HTML elements have implied ARIA semantics.
For example, an HTML <TR>
has an implied ARIA role of row
.
A grid
built from an HTML table
that includes cells that span multiple rows or columns must use HTML rowspan
and colspan
and must not use aria-rowspan
or aria-colspan
.
-
If rows or cells are included in a grid via aria-owns,
they will be presented to assistive technologies after the DOM descendants of the
grid
element unless the DOM descendants are also included in the aria-owns
attribute.
Developing a Keyboard Interface
Unlike native HTML form elements, browsers do not provide keyboard support for graphical user interface (GUI) components that are made accessible with ARIA; authors have to provide the keyboard support in their code.
This section describes the principles and methods for making the functionality of a web page that includes ARIA widgets, such as menus and grids, as well as interactive components, such as toolbars and dialogs, operable with a keyboard.
Along with the basics of focus management, this section offers guidance toward the objective of providing experiences to people who rely on a keyboard that are as efficient and enjoyable as the experiences available to others.
This section covers:
- Understanding fundamental principles of focus movement conventions used in ARIA design patterns.
- Maintaining visible focus, predictable focus movement, and distinguishing between keyboard focus and the selected state.
- Managing movement of keyboard focus between components, e.g., how the focus moves when the Tab and Shift+Tab keys are pressed.
- Managing movement of keyboard focus inside components that contain multiple focusable elements, e.g., two different methods for programmatically exposing focus inside widgets like radio groups, menus, listboxes, trees, and grids.
- Determining when to make disabled interactive elements focusable.
- Assigning and revealing keyboard shortcuts, including guidance on how to avoid problematic conflicts with keyboard commands of assistive technologies, browsers, and operating systems.
Fundamental Keyboard Navigation Conventions
ARIA roles, states, and properties model accessibility behaviors and features shared among GUI components of popular desktop GUIs, including Microsoft Windows, macOS, and GNOME.
Similarly, ARIA design patterns borrow user expectations and keyboard conventions from those platforms, consistently incorporating common conventions with the aim of facilitating easy learning and efficient operation of keyboard interfaces across the web.
For a web page to be accessible, all interactive elements must be operable via the keyboard.
In addition, consistent application of the common GUI keyboard interface conventions described in the ARIA design patterns is important, especially for assistive technology users.
Consider, for example, a screen reader user operating a tree.
Just as familiar visual styling helps users discover how to expand a tree branch with a mouse, ARIA attributes give the tree the sound and feel of a tree in a desktop application.
So, screen reader users will commonly expect that pressing the right arrow key will expand a collapsed node.
Because the screen reader knows the element is a tree, it also has the ability to instruct a novice user how to operate it.
Similarly, voice recognition software can implement commands for expanding and collapsing branches because it recognizes the element as a tree and can execute appropriate keyboard commands.
All this is only possible if the tree implements the GUI keyboard conventions as described in the ARIA tree pattern.
A primary keyboard navigation convention common across all platforms is that the tab and shift+tab keys move focus from one UI component to another while other keys, primarily the arrow keys, move focus inside of components that include multiple focusable elements.
The path that the focus follows when pressing the tab key is known as the tab sequence or tab ring.
Common examples of UI components that contain multiple focusable elements are radio groups, tablists, menus, and grids.
A radio group, for example, contains multiple radio buttons, each of which is focusable.
However, only one of the radio buttons is included in the tab sequence.
After pressing the Tab key moves focus to a radio button in the group, pressing arrow keys moves focus among the radio buttons in the group, and pressing the Tab key moves focus out of the radio group to the next element in the tab sequence.
The ARIA specification refers to a discrete UI component that contains multiple
focusable elements as a composite
widget. The process of controlling focus movement inside a composite is called
managing focus. Following are some ARIA design patterns with example implementations
that demonstrate focus management:
Discernible and Predictable Keyboard Focus
Work to complete this section is tracked by issue 217.
When operating with a keyboard, two essentials of a good experience are the abilities to easily discern the location of the keyboard focus and to discover where focus landed after a navigation key has been pressed.
The following factors affect to what extent a web page affords users these capabilities.
- Visibility of the focus indicator: Users need to be able to easily distinguish the keyboard focus indicator from other features of the visual design. Just as a mouse user may move the mouse to help find the mouse pointer, a keyboard user may press a navigation key to watch for movement. If visual changes in response to focus movement are subtle, many users will lose track of focus and be unable to operate. Authors are advised to rely on the default focus indicators provided by browsers. If overriding the default, consider:
- something about ... Colors and gradients can disappear in high contrast modes.
- Users need to be able to easily distinguish between focus and selection as described in , especially when a component that contains selected elements does not contain the focus.
- ... other considerations to be added ...
- Persistence of focus: It is essential that there is always a component within the user interface that is active (document.activeElement is not null or is not the body element) and that the active element has a visual focus indicator. Authors need to manage events that effect the currently active element so focus remains visible and moves logically. For example, if the user closes a dialog or performs a destructive operation like deleting an item from a list, the active element may be hidden or removed from the DOM. If such events are not managed to set focus on the button that triggered the dialog or on the list item following the deleted item, browsers move focus to the body element, effectively causing a loss of focus within the user interface.
-
Predictability of movement: Usability of a keyboard interface is heavily influenced by how readily users can guess where focus will land after a navigation key is pressed.
Some possible approaches to optimizing predictability include:
-
Move focus in a pattern that matches the reading order of the page's language. In left to right languages, for example, create a tab sequence that moves focus left to right and then top to bottom.
-
Incorporate all elements of a section of the page in the tab sequence before moving focus to another section. For instance, in a page
with multiple columns that has content in a left side bar, center region, and right side bar, build a tab sequence that covers all elements in the left sidebar before focus moves to the first focusable element in the center column.
-
When the distance between two consecutive elements in the tab sequence is significant, avoid movement that would be perceived as backward.
For example, on a page with a left to right language, a jump from the last element in the bottom right of the main content to the top element in a left-hand sidebar is likely to be less predictable and more difficult to follow, especially for users with a narrow field of view.
-
Follow consistent patterns across a site.
The keyboard experience is more predictable when similar pages have similar focus movement patterns.
- Do not set initial focus when the page loads except in cases where:
- The page offers a single, primary function that nearly all users employ immediately after page load.
- Any given user is likely to use the page often.
Focus VS Selection and the Perception of Dual Focus
Occasionally, it may appear as if two elements on the page have focus at the same time.
For example, in a multi-select list box, when an option is selected it may be greyed.
Yet, the focus indicator can still be moved to other options, which may also be selected.
Similarly, when a user activates a tab in a tablist, the selected state is set on the tab and its visual appearance changes.
However, the user can still navigate, moving the focus indicator elsewhere on the page while the tab retains its selected appearance and state.
Focus and selection are quite different.
From the keyboard user's perspective, focus is a pointer, like a mouse pointer; it tracks the path of navigation.
There is only one point of focus at any time and all operations take place at the point of focus.
On the other hand, selection is an operation that can be performed in some widgets, such as list boxes, trees, and tablists.
If a widget supports only single selection, then only one item can be selected and very often the selected state will simply follow the focus when focus is moved inside of the widget.
That is, in some widgets, moving focus may also perform the select operation.
However, if the widget supports multiple selection, then more than one item can be in a selected state, and keys for moving focus do not perform selection.
Some multi-select widgets do support key commands that both move focus and change selection, but those keys are different from the normal navigation keys.
Finally, when focus leaves a widget that includes a selected element, the selected state persists.
From the developer's perspective, the difference is simple -- the focused element is the active element (document.activeElement).
Selected elements are elements that have aria-selected="true"
.
With respect to focus and the selected state, the most important considerations for designers and developers are:
- The visual focus indicator must always be visible.
- The selected state must be visually distinct from the focus indicator.
Deciding When to Make Selection Automatically Follow Focus
in composite widgets where only one element may be selected, such as a tablist or single-select listbox, moving the focus may also cause the focused element to become the selected element. This is called having selection follow focus. Having selection follow focus is often beneficial to users, but in some circumstances, it is extremely detrimental to accessibility.
For example, in a tablist, the selected state is used to indicate which panel is displayed.
So, when selection follows focus in a tablist, moving focus from one tab to another automatically changes which panel is displayed.
If the content of panels is present in the DOM, then displaying a new panel is nearly instantaneous.
A keyboard user who wishes to display the fourth of six tabs can do so with 3 quick presses of the right arrow.
And, a screen reader user who perceives the labels on tabs by navigating through them may efficiently read through the complete list without any latency.
However, if displaying a new panel causes a network request and possibly a page refresh, the effect of having selection automatically focus can be devastating to the experience for keyboard and screen reader users. In this case, displaying the fourth tab or reading through the list becomes a tedious and time-consuming task as the user experiences significant latency with each movement of focus. Further, if displaying a new tab refreshes the page, then the user not only has to wait for the new page to load but also return focus to the tab list.
When selection does not follow focus, the user changes which element is selected by pressing the Enter or Space key.
Keyboard Navigation Between Components (The Tab Sequence)
As explained in section , all interactive UI components need to be reachable via the keyboard. This is best achieved by either including them in the tab sequence or by making them accessible from a component that is in the tab sequence, e.g., as part of a composite component. This section addresses building and managing the tab sequence, and subsequent sections cover making focusable elements that are contained within components keyboard accessible.
The HTML tabindex and SVG tabindex attributes can be used to add and remove elements from the tab sequence.
The value of tabindex can also influence the order of the tab sequence, although authors are strongly advised not to use tabindex for that purpose.
In HTML, the default tab sequence of a web page includes only links and HTML form elements, except In macOS, where it includes only form elements.
macOS system preferences include a keyboard setting that enables the tab key to move focus to all focusable elements.
The default order of elements in the tab sequence is the order of elements in the DOM.
The DOM order also determines screen reader reading order.
It is important to keep the keyboard tab sequence and the screen reader reading order aligned, logical, and predictable as described in .
The most robust method of manipulating the order of the tab sequence while also maintaining alignment with the reading order that is currently available in all browsers is rearranging elements in the DOM.
The values of the tabindex attribute have the following effects.
- tabindex is not present or does not have a valid value
-
The element has its default focus behavior.
In HTML, only form controls and anchors with an HREF attribute are included in the tab sequence.
- tabindex="0"
- The element is included in the tab sequence based on its position in the DOM.
- tabindex="-1"
- The element is not included in the tab sequence but is focusable with element.focus().
- tabindex="X" where X is an integer in the range 1 <= X <= 32767
-
Authors are strongly advised NOT to use these values.
The element is placed in the tab sequence based on the value of tabindex.
Elements with a tabindex value of 0 and elements that are focusable by default will be in the sequence after elements with a tabindex value of 1 or greater.
Keyboard Navigation Inside Components
As described in section , the tab sequence should include only one focusable element of a composite UI component.
Once a composite contains focus, keys other than Tab and Shift + Tab enable the user to move focus among its focusable elements.
Authors are free to choose which keys move focus inside of a composite, but they are strongly advised to use the same key bindings as similar components in common GUI operating systems as demonstrated in .
The convention for where focus lands in a composite when it receives focus as a result of a Tab key event depends on the type of composite. It is typically one of the following.
-
The element that had focus the last time the composite contained focus.
Or, if the composite has not yet contained the focus, the first element.
Widgets that usually employ this pattern include grid and tree grid.
-
The selected element. Or, if there is no selected element, the first element.
Widgets where this pattern is commonly implemented include radio groups, tabs, list boxes, and trees.
Note: For radio groups, this pattern is referring to the checked radio button; the selected state is not supported for radio buttons.
-
The first element.
Components that typically follow this pattern include menubars and toolbars.
The following sections explain two strategies for managing focus inside composite elements: creating a roving tabindex and using the aria-activedescendant property.
Managing Focus Within Components Using a Roving tabindex
When using roving tabindex to manage focus in a composite UI component, the element that is to be included in the tab sequence has tabindex of "0" and all other focusable elements contained in the composite have tabindex of "-1".
The algorithm for the roving tabindex strategy is as follows.
- When the component container is loaded or created, set
tabindex="0"
on the element that will initially be included in the tab sequence and set tabindex="-1"
on all other focusable elements it contains.
-
When the component contains focus and the user presses a navigation key that moves focus within the component, such as an arrow key:
- set
tabindex="-1"
on the element that has tabindex="0"
.
- Set
tabindex="0"
on the element that will become focused as a result of the key event.
- Set focus,
element.focus()
, on the element that has tabindex="0"
.
-
If the design calls for a specific element to be focused the next time the user moves focus into the composite with Tab or Shift+Tab, check if that target element has
tabindex="0"
when the composite loses focus.
If it does not, set tabindex="0"
on the target element and set tabindex="-1"
on the element that previously had tabindex="0"
.
One benefit of using roving tabindex rather than aria-activedescendant to manage focus is that the user agent will scroll the newly focused element into view.
Managing Focus in Composites Using aria-activedescendant
If a component container has an ARIA role that supports the aria-activedescendant property, it is not necessary to manipulate the tabindex attribute and move DOM focus among focusable elements within the container.
Instead, only the container element needs to be included in the tab sequence. When the container has DOM focus, the value of aria-activedescendant on the container tells assistive technologies which element is active within the widget.
Assistive technologies will consider the element referred to as active to be the focused element even though DOM focus is on the element that has the aria-activedescendant property.
And, when the value of aria-activedescendant is changed, assistive technologies will receive focus change events equivalent to those received when DOM focus actually moves.
The steps for using the aria-activedescendant method of managing focus are as follows.
- When the container element that has a role that supports aria-activedescendant is loaded or created, ensure that:
- The container element is included in the tab sequence as described in or is a focusable element of a composite that implements a roving tabindex.
-
It has
aria-activedescendant="IDREF"
where IDREF is the ID of the element within the container that should be identified as active when the widget receives focus.
The referenced element needs to meet the DOM relationship requirements described below.
- When the container element receives DOM focus, draw a visual focus indicator on the active element and ensure the active element is scrolled into view.
- When the composite widget contains focus and the user presses a navigation key that moves focus within the widget, such as an arrow key:
- Change the value of aria-activedescendant on the container to refer to the element that should be reported to assistive technologies as active.
- Move the visual focus indicator and, if necessary, scrolled the active element into view.
-
If the design calls for a specific element to be focused the next time a user moves focus into the composite with Tab or Shift+Tab, check if aria-activedescendant is referring to that target element when the container loses focus.
If it is not, set aria-activedescendant to refer to the target element.
The specification for aria-activedescendant places important restrictions on the DOM relationship between the focused element that has the aria-activedescendant attribute and the element referenced as active by the value of the attribute.
One of the following three conditions must be met.
- The element referenced as active is a DOM descendant of the focused referencing element.
- The focused referencing element has a value specified for the aria-owns property that includes the ID of the element referenced as active.
- The focused referencing element has role of textbox and has aria-controls property referring to an element with a role that supports aria-activedescendant and either:
- The element referenced as active is a descendant of the controlled element.
- The controlled element has a value specified for the aria-owns property that includes the ID of the element referenced as active.
Focusability of disabled controls
By default, disabled HTML input elements are removed from the tab sequence.
In most contexts, the normal expectation is that disabled interactive elements are not focusable.
However, there are some contexts where it is common for disabled elements to be focusable, especially inside of composite widgets.
For example, as demonstrated in the pattern, disabled items are focusable when navigating through a menu with the arrow keys.
Removing focusability from disabled elements can offer users both advantages and disadvantages.
Allowing keyboard users to skip disabled elements usually reduces the number of key presses required to complete a task.
However, preventing focus from moving to disabled elements can hide their presence from screen reader users who "see" by moving the focus.
Authors are encouraged to adopt a consistent set of conventions for the focusability of disabled elements.
The examples in this guide adopt the following conventions, which both reflect common practice and attempt to balance competing concerns.
- For elements that are in the tab sequence when enabled, remove them from the tab sequence when disabled.
-
For the following composite widget elements, keep them focusable when disabled:
-
For elements contained in a toolbar, make them focusable if discoverability is a concern. Here are two examples to aid with this judgment.
-
A toolbar with buttons for moving, removing, and adding items in a list includes buttons for "Up", "Down", "Add", and "Remove".
The "Up" button is disabled and its focusability is removed when the first item in the list is selected.
Given the presence of the "Down" button, discoverability of the "Up" button is not a concern.
-
A toolbar in an editor contains a set of special smart paste functions that are disabled when the clipboard is empty or when the function is not applicable to the current content of the clipboard.
It could be helpful to keep the disabled buttons focusable if the ability to discover their functionality is primarily via their presence on the toolbar.
One design technique for mitigating the impact of including disabled elements in the path of keyboard focus is employing appropriate keyboard shortcuts as described in .
Key Assignment Conventions for Common Functions
The following key assignments can be used in any context where their conventionally associated functions are appropriate.
While the assignments associated with Windows and Linux platforms can be implemented and used in browsers running in macOS,
replacing them with macOS assignments in browsers running on a macOS device can make the keyboard interface more discoverable and intuitive for those users.
In some cases, it may also help avoid system or browser keyboard conflicts.
Keyboard Shortcuts
When effectively designed, keyboard shortcuts that focus an element, activate a widget, or both can dramatically enhance usability of frequently used features of a page or site.
This section addresses some of the keyboard shortcut design and implementation factors that most impact their effectiveness, including:
- Understanding how keyboard shortcuts augment a keyboard interface and whether to make a particular shortcut move focus, perform a function, or both.
- Making key assignments and avoiding assignment conflicts with assistive technologies, browsers, and operating systems.
- Exposing and documenting key assignments.
Designing the Scope and Behavior of Keyboard Shortcuts
This section explains the following factors when determining which elements and features to assign keyboard shortcuts and what behavior to give each shortcut:
- Ensuring discovery through navigation; keyboard shortcuts enhance, not replace, standard keyboard access.
-
Effectively choosing from among the following behaviors:
- Navigation: Moving focus to an element.
- Activation: Performing an operation associated with an element that does not have focus and might not be visible.
- Navigation and activation: Both moving focus to an element and activating it.
- Balancing efficiency and cognitive load: lack of a shortcut can reduce efficiency while too many shortcuts can increase cognitive load and clutter the experience.
Ensure Basic Access Via Navigation
Before assigning keyboard shortcuts, it is essential to ensure the features and functions to which shortcuts may be assigned are keyboard accessible without a keyboard shortcut.
In other words, all elements that could be targets for keyboard shortcuts need to be focusable via the keyboard using the methods described in:
Do not use keyboard shortcuts as a substitute for access via navigation.
This is essential to full keyboard access because:
- The primary means of making functions and their shortcuts discoverable is by making the target elements focusable and revealing key assignments on the element itself.
- If people who rely on the keyboard have to read documentation to learn which keys are required to use an interface, the interface may technically meet some accessibility standards but in practice is only accessible to the small subset of them who have the knowledge that such documentation exists, have the extra time available, and the ability to retain the necessary information.
- Not all devices that depend on keyboard interfaces can support keyboard shortcuts.
Choose Appropriate Shortcut Behavior
The following conventions may help identify the most advantageous behavior for a keyboard shortcut.
-
Move focus when the primary objective is to make navigation more efficient, e.g., reduce the number of times the user must press Tab or the arrow keys.
This behavior is commonly expected when assigning a shortcut to a text box, toolbar, or composite, such as a listbox, tree, grid, or menubar.
This behavior is also useful for moving focus to a section of a page, such as the main content or a complementary landmark section.
- Activate an element without moving focus when the target context of the function is the context that contains the focus. This behavior is most common for command buttons and for functions associated with elements that are not visible, such as a "Save" option that is accessible via a menu. For example, if the focus is on an option in a listbox and a toolbar contains buttons for moving and removing options, it is most beneficial to keep focus in the listbox when the user presses a key shortcut for one of the buttons in the toolbar. This behavior can be particularly important for screen reader users because it provides confirmation of the action performed and makes performing multiple commands more efficient. For instance, when a screen reader user presses the shortcut for the "Up" button, the user will be able to hear the new position of the option in the list since it still has the focus. Similarly, when the user presses the shortcut for deleting an option, the user can
hear the next option in the list and immediately decide whether to press the delete shortcut again.
-
Move focus and activate when the target of the shortcut has a single function and the context of that function is the same as the target.
This behavior is typical when a shortcut is assigned to a button that opens a menu or dialog, to a checkbox, or to a navigation link or button.
Choose Where to Add Shortcuts
Work to draft content for this section is tracked in issue 219.
The first goal when designing a keyboard interface is simple, efficient, and intuitive operation with only basic keyboard navigation support. If basic operation of a keyboard interface is inefficient , attempting to compensate for fundamental design issues, such as suboptimal layout or command structure, by implementing keyboard shortcuts will not likely reduce user frustration. The practical implication of this is that, in most well-designed user interfaces, the percentage of functionality that needs to be accessible via a keyboard shortcut in order to create optimal usability is not very high. In many simple user interfaces, keyboard shortcuts can be entirely superfluous. And, in user interfaces with too many keyboard shortcuts, the excess shortcuts create cognitive load that make the most useful ones more difficult to remember.
Consider the following when deciding where to assign keyboard shortcuts:
- To be written.
Assigning Keyboard Shortcuts
When choosing the keys to assign to a shortcut, there are many factors to consider.
- Making the shortcut easy to learn and remember by using a mnemonic (e.g., Control + S for "Save") or following a logical or spacial pattern.
- Localizing the interface, including for differences in which keys are available and how they behave and for language considerations that could impact mnemonics.
- Avoiding and managing conflicts with key assignments used by an assistive technology, the browser, or the operating system.
Methods for designing a key shortcut scheme that supports learning and memory is beyond the scope of this guide.
Unless the key shortcut scheme is extensive, it is likely sufficient to mimic concepts that are familiar from common desktop software, such as browsers.
Similarly, while localization is important, describing how to address it is left to other resources that specialize in that topic.
The remainder of this section provides guidance balancing requirements and concerns related to key assignment conflicts.
It is typically ideal if key assignments do not conflict with keys that are assigned to functions in the user's operating system, browser, or assistive technology.
Conflicts can block efficient access to functions that are essential to the user, and a perfect storm of conflicts can trap a user.
At the same time, there are some circumstances where intentional conflicts are useful.
And, given the vast array of operating system, browser, and assistive technology keys, it is almost impossible to be certain conflicts do not exist.
So it is also important to employ strategies that mitigate the impact of conflicts whether they are intentional or unknown.
In the following sections, meta key refers to the Windows key on Windows-compatible keyboards and the Command key on MacOS-compatible keyboards.
Operating System Key Conflicts
It is essential to avoid conflicts with keys that perform system level functions, such as application and window management and display and sound control. In general, this can be achieved by refraining from the following types of assignments.
- Any modifier keys + any of Tab, Enter, Space, or Escape.
- Meta key + any other single key (there are exceptions, but they can be risky as these keys can change across versions of operating systems).
- Alt + a function key.
In addition, there are some important application level features that most applications, including browsers, generally support.
These include:
- Zoom
- Copy/Paste
- ... to be continued ...
Assistive Technology Key Conflicts
Even though assistive technologies have collectively taken thousands of key assignments, avoiding conflicts is relatively easy.
This is because assistive technologies have had to develop key assignment schemes that avoid conflicts with both operating systems and applications.
They do this by hijacking specific keys as modifiers that uniquely define their key commands.
For example, many assistive technologies use the Caps Lock key as a modifier.
Deflect assistive technology key conflicts by steering clear of the following types of assignments.
- Caps Lock + any other combination of keys.
- Insert + any combination of other keys.
- Scroll Lock + any combination of other keys.
- macOS only: Control+Option + any combination of other keys.
Browser Key Conflicts
While there is considerable similarity among browser keyboard schemes, the patterns within the schemes are less homogenous. Consequently, it is more difficult to avoid conflicts with browser key assignments. While the impact of conflicts is sometimes mitigated by the availability of two paths to nearly every function -- keyboard accessible menus and keyboard shortcuts, avoiding conflicts with shortcuts to heavily used functions is nonetheless important. Pay special attention to avoiding conflicts with shortcuts to:
- Address or location bar
- Notification bar
- Page refresh
- Bookmark and history functions
- Find functions
Intentional Key Conflicts
While avoiding key conflicts is usually desirable, there are circumstances where intentionally conflicting with a browser function is acceptable or even desirable.
This can occur when the following combination of conditions arises:
- A web application has a frequently used function that is similar to a browser function.
- Users will often want to execute the web application function.
- Users will rarely execute the browser function.
- There is an efficient, alternative path to the browser function.
For example, consider a save function that is available when the focus is in an editor. Most browsers use ... to be continued ...
Grid and Table Properties
To fully present and describe a grid or table, in addition to parsing the headers, rows, and cells using the roles described in the
grid pattern or table pattern,
assistive technologies need to be able to determine:
- The number of rows and columns.
- Whether any columns or rows are hidden, e.g., columns 1 through 3 and 5 through 8 are visible but column 4 is hidden.
- Whether a cell spans multiple rows or columns.
- Whether and how data is sorted.
Browsers automatically populate their accessibility tree with the number of rows and columns in a grid or table based on the rendered DOM.
However, there are many situations where the DOM does not contain the whole grid or table, such as when the data set is too large to fully render.
Additionally, some of this information, like skipped columns or rows and how data is sorted, cannot be derived from the DOM structure.
The below sections explain how to use the following properties that ARIA provides for grid and table accessibility.
Using aria-rowcount
and aria-rowindex
When the number of rows represented by the DOM structure is not the total number of rows available for a table, grid, or treegrid,
the aria-rowcount
property is used to communicate the total number of rows available,
and it is accompanied by the aria-rowindex
property to identify the row indices of the rows that are present in the DOM.
The aria-rowcount
is specified on the element with the table
, grid
, or treegrid
role.
Its value is an integer equal to the total number of rows available, including header rows.
If the total number of rows is unknown, a value of -1
may be specified.
Using a value of -1
indicates that more rows are available to include in the DOM without specifying the size of the available supply.
When aria-rowcount
is used on a table
, grid
, or treegrid
,
a value for aria-rowindex
property is specified on each of its descendant rows, including any header rows.
The value of aria-rowindex
is an integer that is:
- Greater than or equal to 1.
- Greater than the value of
aria-rowindex
on any previous rows.
- Set to the index of the first row in the span if cells span multiple rows.
- Less than or equal to the total number of rows.
WARNING! Missing or inconsistent values of aria-rowindex
could have devastating effects on assistive technology behavior.
For example, specifying an invalid value for aria-rowindex
or setting it on some but not all rows in a table, could cause screen reader table reading functions to skip rows or simply stop functioning.
The following code demonstrates the use of aria-rowcount
and aria-rowindex
properties on a table containing a a hypothetical class list.
<!--
aria-rowcount tells assistive technologies the actual size of the grid
is 463 rows even though only 4 rows are present in the markup.
-->
<table role="grid" aria-rowcount="463">
aria-label="Student roster for history 101"
<thead>
<tr aria-rowindex="1">
<th>Last Name</th>
<th>First Name</th>
<th>E-mail</th>
<th>Major</th>
<th>Minor</th>
<th>Standing</th>
</tr>
</thead>
<tbody>
<!--
aria-rowindex tells assistive technologies that this
row is row 51 in the grid of 463 rows.
-->
<tr aria-rowindex="51">
<td>Henderson</td>
<td>Alan</td>
<td>ahederson56@myuniveristy.edu</td>
<td>Business</td>
<td>Spanish</td>
<td>Junior</td>
</tr>
<!--
aria-rowindex tells assistive technologies that this
row is row 52 in the grid of 463 rows.
-->
<tr aria-rowindex="52">
<td>Henderson</td>
<td>Alice</td>
<td>ahederson345@myuniveristy.edu</td>
<td>Engineering</td>
<td>none</td>
<td>Sophomore</td>
</tr>
<!--
aria-rowindex tells assistive technologies that this
row is row 53 in the grid of 463 rows.
-->
<tr aria-rowindex="53">
<td>Henderson</td>
<td>Andrew</td>
<td>ahederson75@myuniveristy.edu</td>
<td>General Studies</td>
<td>none</td>
<td>Freshman</td>
</tr>
</tbody>
</table>
Using aria-colcount
and aria-colindex
When the number of columns represented by the DOM structure is not the total number of columns available for a table, grid, or treegrid,
the aria-colcount
property is used to communicate the total number of columns available,
and it is accompanied by the aria-colindex
property to identify the column indices of the columns that are present in the DOM.
The aria-colcount
is specified on the element with the table
, grid
, or treegrid
role.
Its value is an integer equal to the total number of columns available.
If the total number of columns is unknown, a value of -1
may be specified.
Using a value of -1
indicates that more columns are available to include in the DOM without specifying the size of the available supply.
When aria-colcount
is used on a table
, grid
, or treegrid
,
a value for aria-colindex
property is either specified on each of its descendant rows or on every cell in each descendant row, depending on whether the columns are contiguous as described below.
The value of aria-colindex
is an integer that is:
- Greater than or equal to 1.
- When set on a cell, greater than the value set on any previous cell within the same row.
- Set to the index of the first column in the span if a cell spans multiple columns.
- Less than or equal to the total number of columns.
WARNING! Missing or inconsistent values of aria-colindex
could have devastating effects on assistive technology behavior.
For example, specifying an invalid value for aria-colindex
or setting it on some but not all cells in a row, could cause screen reader table reading functions to skip cells or simply stop functioning.
Using aria-colindex
When Column Indicies Are Contiguous
When all the cells in a row have column index numbers that are consecutive integers,
aria-colindex
can be set on the row element with a value equal to the the index number of the first column in the set.
Browsers will then compute a column number for each cell in the row.
The following code shows a grid with 16 columns, of which columns 2 through 5 are displayed to the user.
Because the set of columns is contiguous, aria-colindex
can be placed on each row.
<div role="grid" aria-colcount="16">
<div role="rowgroup">
<div role="row" aria-colindex="2">
<span role="columnheader">First Name</span>
<span role="columnheader">Last Name</span>
<span role="columnheader">Company</span>
<span role="columnheader">Address</span>
</div>
</div>
<div role="rowgroup">
<div role="row" aria-colindex="2">
<span role="gridcell">Fred</span>
<span role="gridcell">Jackson</span>
<span role="gridcell">Acme, Inc.</span>
<span role="gridcell">123 Broad St.</span>
</div>
<div role="row" aria-colindex="2">
<span role="gridcell">Sara</span>
<span role="gridcell">James</span>
<span role="gridcell">Acme, Inc.</span>
<span role="gridcell">123 Broad St.</span>
</div>
…
</div>
</div>
Using aria-colindex
When Column Indicies Are Not Contiguous
When the cells in a row have column index numbers that are not consecutive integers, aria-colindex
needs to be set on each cell in the row.
The following example shows a grid for an online grade book where the first two columns contain a student name and subsequent columns contain scores.
In this example, the first two columns with the student name are shown, but the score columns have been scrolled to show columns 10 through 13.
Columns 3 through 9 are not visible so are not in the DOM.
<table role="grid" aria-rowcount="463" aria-colcount="13">
aria-label="Student grades for history 101"
<!--
aria-rowcount and aria-colcount tell assistive technologies
the actual size of the grid is 463 rows by 13 columns,
which is not the number rows and columns found in the markup.
-->
<thead>
<tr aria-rowindex="1">
<!--
aria-colindex tells assistive technologies that the
following columns represent columns 1 and 2 of the total data set.
-->
<th aria-colindex="1">Last Name</th>
<th aria-colindex="2">First Name</th>
<!--
aria-colindex tells users of assistive technologies that the
following columns represent columns 10, 11, 12, and 13 of
the overall data set of grades.
-->
<th aria-colindex="10">Homework 4</th>
<th aria-colindex="11">Quiz 2</th>
<th aria-colindex="12">Homework 5</th>
<th aria-colindex="13">Homework 6</th>
</tr>
</thead>
<tbody>
<tr aria-rowindex="50">
<!--
every cell needs to define the aria-colindex attribute
-->
<td aria-colindex="1">Henderson</td>
<td aria-colindex="2">Alan</td>
<td aria-colindex="10">8</td>
<td aria-colindex="11">25</td>
<td aria-colindex="12">9</td>
<td aria-colindex="13">9</td>
</tr>
<tr aria-rowindex="51">
<td aria-colindex="1">Henderson</td>
<td aria-colindex="2">Alice</td>
<td aria-colindex="10">10</td>
<td aria-colindex="11">27</td>
<td aria-colindex="12">10</td>
<td aria-colindex="13">8</td>
</tr>
<tr aria-rowindex="52">
<td aria-colindex="1">Henderson</td>
<td aria-colindex="2">Andrew</td>
<td aria-colindex="10">9</td>
<td aria-colindex="11">0</td>
<td aria-colindex="12">29</td>
<td aria-colindex="13">8</td>
</tr>
</tbody>
</table>
Defining cell spans using aria-colspan
and aria-rowspan
For tables, grids, and treegrids created using elements other than HTML table
elements,
row and column spans are defined with the aria-rowspan
and aria-colspan
properties.
The value of aria-colspan
is an integer that is:
- Greater than or equal to 1.
- less than the value that would cause the cell to overlap the next cell in the same row.
The value of aria-rowspan
is an integer that is:
- Greater than or equal to 0.
- 0 means the cell spans all the remaining rows in its row group.
- less than the value that would cause the cell to overlap the next cell in the same column.
The following example grid has a two row header.
The first two columns have headers that span both rows of the header.
The subsequent 6 columns are grouped into 3 pairs with headers in the first row that each span two columns.
<div role="grid" aria-rowcount="463">
aria-label="Student grades for history 101"
<div role="rowgroup">
<div role="row" aria-rowindex="1">
<!--
aria-rowspan and aria-colspan provide
assistive technologies with the correct data cell header information
when header cells span more than one row or column.
-->
<span role="columnheader" aria-rowspan="2">Last Name</span>
<span role="columnheader" aria-rowspan="2">First Name</span>
<span role="columnheader" aria-colspan="2">Test 1</span>
<span role="columnheader" aria-colspan="2">Test 2</span>
<span role="columnheader" aria-colspan="2">Final</span>
</div>
<div role="row" aria-rowindex="2">
<span role="columnheader">Score</span>
<span role="columnheader">Grade</span>
<span role="columnheader">Score</span>
<span role="columnheader">Grade</span>
<span role="columnheader">Total</span>
<span role="columnheader">Grade</span>
</div>
</div>
<div role="rowgroup">
<div role="row" aria-rowindex="50">
<span role="cell">Henderson</span>
<span role="cell">Alan</span>
<span role="cell">89</span>
<span role="cell">B+</span>
<span role="cell">72</span>
<span role="cell">C</span>
<span role="cell">161</span>
<span role="cell">B-</span>
</div>
<div role="row" aria-rowindex="51">
<span role="cell">Henderson</span>
<span role="cell">Alice</span>
<span role="cell">94</span>
<span role="cell">A</span>
<span role="cell">86</span>
<span role="cell">B</span>
<span role="cell">180</span>
<span role="cell">A-</span>
</div>
<div role="row" aria-rowindex="52">
<span role="cell">Henderson</span>
<span role="cell">Andrew</span>
<span role="cell">82</span>
<span role="cell">B-</span>
<span role="cell">95</span>
<span role="cell">A</span>
<span role="cell">177</span>
<span role="cell">B+</span>
</div>
</div>
</div>
Note: When using HTML table
elements,
use the native semantics of the th
and td
elements to define row and column spans
by using the rowspan
and colspan
attributes.
Indicating sort order with aria-sort
When rows or columns are sorted, the aria-sort
property can be applied to a column or row header to indicate the sorting method.
The following table describes allowed values for aria-sort
.
It is important to note that ARIA does not provide a way to indicate levels of sort for data sets that have multiple sort keys.
Thus, there is limited value to applying aria-sort
with a value other than none
to more than one column or row.
The following example grid uses aria-sort
to indicate the rows are sorted from the highest "Quiz 2" score to the lowest "Quiz 2" score.
<table role="grid" aria-rowcount="463" aria-colcount="13"
aria-label="Student grades for history 101">
<thead>
<tr aria-colindex="10" aria-rowindex="1">
<th>Homework 4</th>
<!--
aria-sort indicates the column with the heading
"Quiz 2" has been used to sort the rows of the grid.
-->
<th aria-sort="descending">Quiz 2</th>
<th>Homework 5</th>
<th>Homework 6</th>
</tr>
</thead>
<tbody>
<tr aria-colindex="10" aria-rowindex="50">
<td>8</td>
<td>30</td>
<td>9</td>
<td>9</td>
</tr>
<tr aria-colindex="10" aria-rowindex="51">
<td>10</td>
<td>29</td>
<td>10</td>
<td>8</td>
</tr>
<tr aria-colindex="10" aria-rowindex="52">
<td>9</td>
<td>9</td>
<td>27</td>
<td>6</td>
</tr>
<tr aria-colindex="10" aria-rowindex="53">
<td>9</td>
<td>10</td>
<td>26</td>
<td>8</td>
</tr>
<tr aria-colindex="10" aria-rowindex="54">
<td>9</td>
<td>7</td>
<td>24</td>
<td>6</td>
</tr>
</tbody>
</table>