Carousel
A carousel presents a series of content panels (slides) that are rotated into view either manually under user control or automatically. One or more slides may be displayed at a time. A carousel often is used to display a set of images, one in each slide.
Common carousel styles include:
- A basic carousel has previous and next slide controls and, if automatically rotated, a rotation (pause/play) control.
- A carousel with a slide picker—a set of buttons often styled as small dots—rather than previous and next slide controls.
Though they may use different means, all users should be presented with the same content and have an equivalent experience.
Carousel structure
An accessible carousel is constructed with a DOM order optimized for the linear reading experience of screen reader users and the keyboard focus order, placing controls before content and using CSS to re-position items to achieve the desired visual design when necessary. When a carousel rotates automatically, a pause button should be the first control, such as the following:
1<section2 class="carousel"3 aria-roledescription="carousel"4 aria-labelledby="mySlidesTitle">5 <h2 id="mySlidesTitle">My Slide Show</h2>6 <div class="carousel__controls">7 <button id="mySlidesRotationControl">8 Stop automatic slide show9 </button>10 <!-- other controls -->11 </div>12 <div class="carousel__slides">13 <div14 class="slide"15 role="group"16 aria-roledescription="slide"17 aria-label="1 of N">18 <!-- first slide content -->19 </div>20 <!-- more slides -->21 </div>22</section>
Note that if the only controls present are for selecting a specific slide and the slides do not automatically rotate, the accessibility guidelines for a Tablist are more appropriate than those found here.
Carousel Container
Carousel has role
A carousel should be enclosed within a container element with an ARIA role
appropriate for its part in the page information architecture. If the carousel
should be included in the page summary, it should have the landmark role of
region
, either by use of the HTML <section>
element or with the attribute
role="region"
. Otherwise, the container element should have the attribute
role="group"
.
To further identify it, the container element should also have the attribute
aria-roledescription="carousel"
.
Carousel is labelled
The carousel container should also have a unique accessibility label. To avoid redundancy (screen readers will announce its role), the accessibility label should not include the word “carousel.”
If a carousel has a visible label, set the aria-labelledby
property to the ID
of the label’s containing element to provide an accessibility label. Otherwise,
set aria-label
.
Controls
Controls have labels
To minimize their visual footprint, carousel controls are commonly styled as icons. Screen reader users need accessibility labels. Techniques to provide them include the following:
- Set the
aria-label
property on the control element. - Use CSS to visually hide text inside the control element.
- On an SVG icon, set
aria-labelledby
to the SVG<title>
ID.
Controls have contrast
When slide content varies or is unknown, controls that overlay slides often run into problems meeting minimum contrast requirements. (Icons should have a contrast ratio of 3:1 or more with background.) Either place controls outside the slide area or include a background for each control such that meaningful visual contrast always has sufficient contrast.
Rotation is controllable
If a carousel rotates automatically, users may want or need to pause or restart rotation when browsing its content. And not all users can see that a carousel is automatically rotating. An easily located rotation control not only helps users control the rotation but also informs users of the carousel’s autorotation state: rotating or not.
Place a Button to stop (and restart) automatic rotation in the DOM order
before other controls. Rather than setting aria-pressed
with an unchanging
label, best practice is to vary the label to indicate the action the button will
perform, such as “Pause slide show” and “Start slide show.”
Focus pauses rotation
To avoid an unexpected (and unwanted) change of context, the carousel should pause rotation when either of the following conditions occur:
- While any element in the carousel other than the rotation control button has keyboard focus
- While a slide has pointer device “hover”—after
pointerenter
and beforepointerleave
events
Automatic rotation may resume when neither of those conditions are present.
Prefers reduced motion
A carousel with an automatic rotation feature should not rotate automatically on page load for users that have selected reduced motion in their system settings. The reduced-motion preference can be captured in JavaScript as in the following example:
1if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {2 // disable auto-rotation3}
Slides are navigable
In a basic carousel, controls exist for manually navigating to the next or
previous slide have the role of button with aria-controls
set to the ID of
the element containing the set of slides.
Alternatively, a carousel can provide a slide picker where uses can select any slide. A common pattern is a list of icon buttons styled as small circles with the button representing the shown slide clearly indicated.
As a best practice, slide navigation buttons should be grouped together, placed before slide content so that screen reader users who navigate linearly through DOM content can easily find them. When necessary, use CSS to position them differently to adopt a desired visual style. User experience is more important than achieving strict alignment of visual and DOM order.
Slide picker is a tablist
While the set of slide-picker buttons could be grouped with each button in the tabbing order, keyboard users have a better experience when the buttons are placed in a Tablist, where only the selected button corresponding to the slide showing is in the tabbing order. In this pattern, we refer to the buttons as “tabs”:
- The slide-picker container has
role="tablist"
and an accessibility label that tells what it lists, such asaria-label="Slide selectors"
. - Each slide-picker tab has
role="tab"
witharia-controls
set to the ID of the slide it selects and an accessibility label that tells what it controls, such asaria-label="Slide 3 of 6"
. - A tab controlling the currently shown slide is in its selected state, with
aria-selected="true"
. All other tabs havearia-selected="false"
. - Only the selected tab is in the tabbing order with
tabindex="0"
set unless using the native button element. All other tabs havetabindex="-1"
set so that they can be programmatically focused. - Use visual focus indicators that meet contrast requirements. In addition to the indicator on the focused tab, display an indicator on the entire tablist when any tab has focus. Doing so will help sighted keyboard users understand that it is a tablist they can operate with arrow keys.
- The
Right Arrow
key moves focus to and selects the next button, wrapping to the first if last. - The
Left Arrow
key moves focus to and selects the previous button, wrapping to the last if first. - The
Home
key moves focus to and selects the first button. - The
End
key moves focus to and selects the last button.
Slides
Slides have role
Each slide should be assigned an ARIA role with
aria-roledescription="slide"
. If the carousel has slide picker controls using
the Tabs Pattern, each slide has role="tabpanel"
. Otherwise, set
role="group"
on the slide.
Slides have labels
Each slide should also have a unique accessibility label, for example, by
setting aria-label="3 of 6"
. To avoid redundancy (screen readers will announce
its role), the accessibility label should not include the word “slide.”
Inactive slides hidden
Slides that are not visually displayed should not be available to screen reader
users. Otherwise, users could become disoriented or confused by slide changes or
slide control operations. Slides can be hidden visually and from screen reader
users by setting the CSS property display: none
on inactive slides.
Manual slide changes announced
Include slide content in an ARIA live region only when automatic rotation is turned off. Screen reader users then benefit from the immediate auditory response to their action to change slides. Otherwise, when rotation is automatic, an automatic announcement of slide changes can simply be annoying—slide content would be announced even when attention is elsewhere.
For an automatically rotating carousel, set aria-live="off"
on the element
containing the set of slides, then use JavaScript to change its value to
polite
when automatic rotation is stopped or paused.
Summary of tests
Test | WCAG Success Criteria | Severity |
---|---|---|
Carousel has role | 4.1.2 Name, Role, Value — A | Moderate |
Carousel is labelled | 4.1.2 Name, Role, Value — A | Moderate |
Controls have labels | 4.1.2 Name, Role, Value — A | Serious |
Controls have contrast | 1.4.11 Non-text Contrast — AA | Serious |
Rotation is controllable | 2.2.2 Pause, Stop, Hide — A | Serious |
Focus pauses rotation | 2.2.2 Pause, Stop, Hide — A | Serious |
Prefers reduced motion | 2.2.2 Pause, Stop, Hide — A | Serious |
Slides are navigable | 2.1.1 Keyboard — A | Serious |
Slide picker is a tablist | Best practice | Moderate |
Slides have role | 4.1.2 Name, Role, Value — A | Moderate |
Slides have labels | 4.1.2 Name, Role, Value — A | Moderate |
Inactive slides hidden | Best practice | Moderate |
Manual slide changes announced | 4.1.3 Status Messages — AA | Serious |