You are here

Sliders, Tab panels, accordion and carousel

  • Recognize the elements of an accessible slider
  • Identify what makes an accordion accessible
  • Identify the elements of an accessible tab panel
  • Explain the challenges of making a carousel accessible

 

 

Sliders

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

  • tabindex="[0 | -1]"
  • role="slider"
  • aria-valuemin="[number]"
  • aria-valuemax="[number]"
  • aria-valuenow="[number]"
Suggested Reading: Additional information about creating accessible sliders (Links to an external site.)Links to an external site. can be found in the WAI-ARIA Best Practices

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.

Adding Keyboard Operability

WAI-ARIA authoring practices defines recommended keyboard functionality for a slider, listed below.

Keyboard Interaction for a Slider

  • Right Arrow: Increase the value of the slider by one step.
  • Up Arrow: Increase the value of the slider by one step.
  • Left Arrow: Decrease the value of the slider by one step.
  • Down Arrow: Decrease the value of the slider by one step.
  • Home: Set the slider to the first allowed value in its range.
  • End: Set the slider to the last allowed value in its range.
  • Page Up (Optional): Increment the slider by an amount larger than the step change made by Up Arrow.
  • Page Down (Optional): Decrement the slider by an amount larger than the step change made by Down Arrow.
Note
  1. Focus is placed on the slider (the visual object that the mouse user would move, also known as the thumb).
  2. In some circumstances, reversing the direction of the value change for the keys specified above, e.g., having Up Arrow decrease the value, could create a more intuitive experience.

Source W3C WAI-ARIA 1.1 Best Practices (Links to an external site.)Links to an external site.

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.

Accessible Slider in Action

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.

 

 

Accordions

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

  • aria-multiselectable = "(true | false)"
  • role="heading"
  • role="button"
  • aria-controls="[panel id]"
  • tabindex="0"
  • role="region"
  • aria-hidden= "(true | false)"
  • aria-expanded= "(true | false)"
Suggested Reading: For details on constructing accessible accordions, refer to: WAI-ARIA Authoring Practices: Accordion (Links to an external site.)Links to an external site.

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.

Adding Keyboard Operability

WAI-ARIA best practices defines all recommended accordion keyboard functionality, listed below. In our example, only the required keyboard events are included. 

Keyboard Interaction for Accordions

  • Enter or Space:
    • When focus is on the accordion header for a collapsed panel, expands the associated panel. If the implementation allows only one panel to be expanded, and if another panel is expanded, collapses that panel.
    • When focus is on the accordion header for an expanded panel, collapses the panel if the implementation supports collapsing. Some implementations require one panel to be expanded at all times and allow only one panel to be expanded; so they do not support a collapse function.
  • Down Arrow (Optional): If focus is on an accordion header, moves focus to the next accordion header. If focus is on the last accordion header, either does nothing or moves focus to the first accordion header.
  • Up Arrow (Optional): If focus is on an accordion header, moves focus to the previous accordion header. If focus is on the first accordion header, either does nothing or moves focus to the last accordion header.
  • Home (Optional): When focus is on an accordion header, moves focus to the first accordion header.
  • End (Optional): When focus is on an accordion header, moves focus to the last accordion header.
  • Ctrl+Page Down (Optional): If focus is inside an accordion panel or on an accordion header, moves focus to the next accordion header. If focus is in the last accordion header or panel, either does nothing or moves focus to the first accordion header.
  • Ctrl+Page Up (Optional): If focus is inside an accordion panel, moves focus to the header for that panel. If focus is on an accordion header, moves focus to the previous accordion header. If focus is on the first accordion header, either does nothing or moves focus to the last accordion header.

Source: WAI-ARIA Accordion Design Patterns (Links to an external site.)Links to an external site.

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.

Accessible Accordion in Action

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

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

  • role="tablist"
  • role="tabpanel"
  • role="tab"
  • aria-hidden="[true|false]"
  • tabindex = [0 | -1]
  • aria-controls="[panel id]"
  • aria-selected="[ true | false ]"
Suggested Reading: Additional information about creating accessible tab panels (Links to an external site.)Links to an external site. can be found in the WAI-ARIA Authoring Practices.

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.

Adding Keyboard Operability

W3C describes authoring practices for tab panel keyboard interactions as follows.

Keyboard Interaction for Tab Panels

For the tab list:

  • Tab: When focus moves into the tab list, places focus on the active 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.
  • When focus is on a tab element in a horizontal tab list:
    • Left Arrow: moves focus to the previous tab. If focus is on the first tab, moves focus to the last tab. Optionally, activates the newly focused tab (See note below).
    • Right Arrow: Moves focus to the next tab. If focus is on the last tab element, moves focus to the first tab. Optionally, activates the newly focused tab (See note below).
  • When focus is on a tab in a tablist with either horizontal or vertical orientation:
    • Space or Enter: Activates the tab if it was not activated automatically on focus.
    • Home (Optional): Moves focus to the first tab
    • End (Optional): Moves focus to the last tab.
    • Shift+F10: If the tab has an associated pop-up menu, opens the menu.
    • Delete (Optional): If deletion is allowed, deletes (closes) the current tab element and its associated tab panel. If any tabs remain, sets focus to the tab following the tab that was closed and activates the newly focused tab. Alternatively, or in addition, the delete function is available in a context menu.
Note
  1. It is recommended that tabs activate automatically when they receive focus as long as their associated tab panels are displayed without noticeable latency. This typically requires tab panel content to be preloaded. Otherwise, automatic activation slows focus movement, which significantly hampers users’ ability to navigate efficiently across the tab list. For additional guidance, see 5.4 Deciding When to Make Selection Automatically Follow Focus (Links to an external site.)Links to an external site..
  2. If the tabs in a tab list are arranged vertically:
    1. Down Arrow performs as Right Arrow is described above.
    2. Up Arrow performs as Left Arrow is described above.
  3. If the tab list is horizontal, it does not listen for Down Arrow or Up Arrow so those keys can provide their normal browser scrolling functions even when focus is inside the tab list.

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.

Accessible Tab Panel in Action

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

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

  • role="region"
  • aria-live="polite"
  • tabindex="0"
  • aria-describedby="[id of div with instructions]"
  • aria-hidden="(true | false)"
Suggested Reading: The Carousel Tutorial (Links to an external site.)Links to an external site. from the W3C provides additional details on constructing accessible 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.

Adding Keyboard Operability

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.

Accessible Carousel in Action

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.