Sliders typically allow users to select a value between minimum and maximum values by dragging a slider thumb along a slider bar or track.
WAI-ARIA roles, states, and properties used in a slider
The following JSFiddle presents a typical slider widget. Review the JavaScript and HTML markup, and test the slider presented under the Result tab with ChromeVox to understand how it functions without any accessibility features added. You can work in JSFiddle itself by clicking the “Edit in JSFiddle” at the top, right-hand side, copying the accessibility/WAI-ARIA code described below to fix the accessibility of the slider before completing Activity 8 on the page that follows.Skip JSFiddle
Define some instructions that describe how to use the slider for screen reader users.
Add a tabindex="0"
to make the slider thumb keyboard focusable. Assign a role="slider"
to the text box so it announces as a slider instead of a text entry field. Set aria-valuemin
, aria-valuemax
, and aria-valuenow
values, and reference the instructions with aria-describedby
. Using .on('keydown')
reference the onKeyDown
function to add keyboard operability to the slider.
Create a <div>
for the screen reader instructions.
Dynamically set the value of aria-valuenow
based on the value at which the slider thumb is located.
Remove keyboard access from the original text field.
WAI-ARIA authoring practices defines recommended keyboard functionality for a slider, listed below.
Source W3C WAI-ARIA 1.1 Best Practices
Add keyboard event handling to our slider widget. In our case, we will add Left and Right Arrow controls for moving the slider thumb along the slider bar, and End and Home controls for moving the slider thumb between the start and end of the slider bar.
Watch the following video of ChromeVox interacting with a slider, using the Arrow keys to move the slider thumb along the slider bar, and Home and End keys to move the slider thumb between the start and the end of the slider bar. You may notice that ChromeVox interprets “min” as “minute” rather than min and max that define the range along the slider bar. Aim to have the slider you update in the activity that follows on the next page operate and announce like the one in the video.
Accordion widgets can come in single or multiselect formats, in which one or multiple panels can be opened at once, respectively. They are typically used to reduce the space that content occupies and to reduce scrolling. Accordions are made up of Accordion Headers and Accordion Panels. The accordion headers control the display of their associated accordion panel.
The WAI-ARIA roles, states, and properties used in an accordion
The following JSFiddle presents a typical accordion widget. Review the JavaScript and HTML markup, and test the accordion presented under the Result tab with ChromeVox to understand how it functions without any accessibility features added. You can work in JSFiddle itself by clicking the “Edit in JSFiddle”, copying the accessibility/WAI-ARIA code described below to fix the accessibility of the accordion before completing Activity 9 on the page that follows.Skip JSFiddle
First, add the accordion to the landmarked regions by assigning role="region"
to the opening <DL>
element when the accordion is initialized, adding the region role to the init()
function.
Next add the aria-multiselectable
attribute to the <DL>
, to be dynamically set to true or false based on plugin configuration settings. This lets a user know that more than one accordion panel can be opened when set to TRUE, or only a single panel when set to FALSE. Refer to the $(document).ready
block in the HTML, where the assignment takes place.
The semantics of the children of the <DL>
element, which was assigned role="presentation"
, will also have their definition list semantics removed. Add the accordion semantics role="heading"
to assign a heading role to the <DT>
elements. The aria-level
attribute might be used to implement nested accordion panels, but for the purpose of this course a simplified version should be sufficient.
Add a <div>
inside the header (i.e. DT) and define its role
as a button. The button is given an aria-controls
attribute to define which of the accordion panels it controls. By default the toggle state is set to false with aria-expanded="false"
to be updated dynamically when the button is clicked or key pressed. Finally add tabindex="0"
to the button (<div>
) to make it keyboard focusable.
The tabindex will make the button focusable, but it will not make it clickable. The .on()
jQuery function adds a click event to the button, but a keypress event must also be added. Adding .on('keydown')
activates the onKeyDown
function, defined below, so the accordion headers operate with both a mouse click and a keypress.
Finally the accordion panel semantics are added, defining the <DD>
elements that has had its semantics removed when role="presentation"
was added to the parent <DL>
. Panels are given a generic role="region"
, to make the panel browsable in the landmarks list, set to be hidden by default with aria-hidden="true"
so all panels are closed when the page loads. Tabindex="0"
is also added to make the panels keyboard focusable so the content of the panel is read as the user navigates to them.
WAI-ARIA best practices defines all recommended accordion keyboard functionality, listed below. In our example, only the required keyboard events are included.
Source: WAI-ARIA Accordion Design Patterns
The following onKeyDown
function has been created to add keyboard operability to the header elements of the accordion, allowing both space bar and Enter keys to operate the toggles (i.e. headers) that open and close panels, and the Arrow keys to move between the accordion headers. By default, users can navigate between headers, and between headers and panels using the Tab key.
Watch the following video to see how ChromeVox interacts with an accordion. The Tab key is used to navigate into the accordions, to move between accordion headers, and to move between accordion headers and panels. Arrow keys can also be used to move between accordion headers but not from headers to an associated panel. Aim to have the accordion you update in the activity on the following page operate and announce like the one in the video.
Tab panels, much like accordions, are often used to conserve space and reduce scrolling. They are typically made up of a tablist that contains a series of tabs, each tab controlling the display of a panel. As each tab is activated, its associated panel is displayed and other panels are hidden. When a tab is selected it is highlighted to indicate which tab and panel are active.
WAI-ARIA roles, states, and properties used in a tab panel
The following JSFiddle presents a typical tab panel widget. Review the JavaScript and HTML markup, and test the tab panel presented under the Result tab with ChromeVox to understand how it functions without any accessibility features added. You can work in JSFiddle itself by clicking the “Edit in JSFiddle”, copying the accessibility/WAI-ARIA code described below to fix the accessibility of the tab panel before completing Activity 10 on the page that follows.Skip JSFiddle
In our case we are generating the tabs for each child <div>
defined in the HTML, though tabs and tab panels could be static HTML. The tablist is made up of a <ul>
and child <li>
elements. We assign role="tablist"
to the <ul>
to remove its list semantics and replace it with tab panel semantics.
Next we add WAI-ARIA to the panels, assigning role="tabpanel"
to each of the original <div>
elements, hide them by default with aria-hidden="true"
, and finally adding tabindex="0"
to make the panels keyboard focusable.
The tabs themselves are now defined, replacing the list item semantics with tab semantics adding role="tab"
to each of the <li>
elements generated. We also need to define which tab controls which tabpanel, dynamically generating aria-controls="[panel_id]"
for each of the tabs.
When a tab is selected, we want to remove selection from other tabs with aria-selected="false"
, and remove keyboard access temporarily by assigning tabindex="-1"
to the unselected tabs, so that that tabpanel becomes next in the tab order, and users can navigate directly from the tab to the panel without having to pass through the other tabs in the tablist.
Likewise, when a tab is selected we assign aria-selected="true"
so screen readers announce the selected tab, and we add tabindex="0"
as the roving tabindex to make that tab focusable.
As the tabs change, hide all the panels with aria-hidden="true"
so screen readers do not see them, then open the panel the current tab controls with aria-hidden="false"
so screen readers can see the active panel. These are added to the end of the selectTab()
function.
W3C describes authoring practices for tab panel keyboard interactions as follows.
For the tab list:
tab
element . When the tab list contains the focus, moves focus to the next element in the page tab sequence outside the tablist, which is typically either the first focusable element inside the tab panel or the tab panel itself.As usual, the tab panel needs to be keyboard operable to be accessible to screen readers. The onKeyDown()
function is added to the functions, to add arrow key navigation between tabs, and between tabs and panels. Tab navigation and Enter keys are enabled by default and do not need to be defined here.
The onKeyDown
function is then added to each tab, referenced with jQuery's .on('keydown')
function, added to the init()
function's $tab
definition.
Now with keyboard access and WAI-ARIA added to define the semantics of the tab panel, it should be fully functional for screen readers.
Watch the following video showing ChromeVox interacting with a tab panel. The Tab key is used to navigate into the tab panel, and to the first tab. The Arrow keys are used to move between tabs, and when on a tab, the Tab key is used to navigate to the associated panel. While on a panel, Shift+Tab is used to return to the tablist. There might also be Up and Down Arrows enabled to move between tabs and panels, though we have not enabled them here. Aim to have the tab panel you update in the activity coming up on the next page operate and announce itself like the one in the video.
Carousels are typically used to present a series of panels or images that rotate at a particular frequency.
WAI-ARIA roles, states, and properties used in carousels
The following JSFiddle presents a typical carousel widget. Review the JavaScript and HTML markup, and test the carousel presented under the Result tab with ChromeVox to understand how it functions without any accessibility features added. You can work in JSFiddle itself by clicking “Edit in JSFiddle”, copying the accessibility/WAI-ARIA code described below to fix the accessibility of the accordion before completing Activity 11 on the page that follows.Skip JSFiddle
Though instructions are not always required, they can be helpful for screen reader users when there is non-standard keyboard navigation. In our case we’ll add a few words and assign them to the “instructions” variable in the default settings of the init()
function for the carousel. The instructions will be rendered in its own div and referenced with aria-describedby
a little later in the code.
We’ll define a few attributes when the carousel is initialized, giving it a role="region"
to add it to the landmarks, add a tabindex
to make it keyboard focusable, and reference the ID of the instructions <div>
with aria-describedby
. Add keyboard operability with .on('keydown')
and a reference to the onKeyDown
function, described below.
Screen reader users will not need the Next/Previous controls, so hide them. They will be using the Arrow keys instead, defined in the onKeyDown
function further below.
Hide images from screen readers. Notice that the alt
text for the images are defined in the HTML but left empty so it is not read in this case. Screen readers will read the figcaptions
.
Add screen reader instructions by generating a <div>
that contains the instruction text defined earlier, and hide the <div>
by default. The instructions are read when the carousel receives focus, and the aria-describedby
attribute is dynamically added to reference the instructions.
Add an aria-live
attribute to the stopTimer
function, and set its value to polite
so content updating in the live region announces when a screen reader is not reading elsewhere on the page. The content of the visible carousel panel is read automatically when it is in focus, manually navigating between panels with the Arrow keys.
Remove the live region when focus on the carousel is removed, in the startTimer
function, so the live region stops reading when the timer is reactivated onblur
, and does not interfere with the screen reader reading elsewhere on the page.
Hide the active slide from screen readers with aria-hidden="true"
, and make the next slide visible to screen readers with aria-hidden="false"
, in the gotoSlide
function.
Add keyboard operations for the carousel, pulling keyboard events from ik_utils.js to use Left and Right Arrows for moving between panels in the carousel, and the Esc key to exit the carousel and resume automatic rotation.
Watch the following video to see how ChromeVox interacts with a carousel. The carousel rotates automatically when focus is elsewhere on the page. When it receive focus, rotation stops, and navigation instructions are read. The Left and Right Arrow keys are used to move manually between panels in the carousel while it has focus. The contents of each panel are read through a live region, dynamically added to the main container <div>
when the carousel has focus. Using the Tab key while the carousel has focus, sends focus to any focusable element within the panel that is in view, a link to the person who shared the photo in this case. Aim to have the carousel you update in the activity on the following page operate and announce like the one in the video.