Carousels! They aren’t effective or popular with real users, and yet they can be found all over the web. Often the result of competing internal priorities, carousels might be thought of as a manifestation of unclear business goals or unresolved internal conflicts.
Regardless of why they are used, one thing is practically universal — carousels are almost always inaccessible to disabled users. In this article we’ll look at common accessibility barriers found in carousels, talk through some good solutions, and then connect you with some practical resources you can start using right now to make your carousels more accessible!
What is a carousel, anyway?
Those of us who design or build web experiences can usually spot a carousel from a mile (or kilometer) away. They are a region of the page that acts sort of like a slideshow, allowing users to move through a bunch of content that would normally not be possible to fit into that same amount of space.
Carousels vary quite a bit in their use cases, features, and implementations, which can make it pretty difficult to come up with a precise, universal definition. What we can do, though, is list out the most common characteristics they can have, such as:
- May have one or more slides visible at a time.
- May have slides that contain simple content (like a single image each) or complex content (like form fields and tooltips and all sorts of other complicated things).
- May have controls to navigate to previous and next slides.
- May have controls to jump to specific slides.
- May automatically advance through slides all on its own, at whatever pace the owners felt like using.
- May be oriented horizontally, vertically, or even in 3D!
- May wrap its slides around when a user tries to move past the end or beginning of the set (sometimes called “infinite scrolling”).
- May visually emphasize a single slide to show that it is “active”.
Common accessibility issues in carousels
Although carousels can vary quite a bit in their features and implementations, there are a few things that they consistently get wrong for accessibility. Through extensive live user testing with native screen reader and keyboard-only users at Accessible360 across hundreds of websites, we find the following issues over and over again:
- Screen reader users very often don’t know when their virtual cursor enters or leaves a carousel, making it difficult for them to know that it even exists or how to get out of it.
- Nearly every carousel is built differently (even if they look the same), so screen reader users can have a tough time building up a consistent mental model that makes carousels easier to navigate later on.
- Many carousels do not hide their non-visible slides from all users, forcing keyboard and screen reader users to go through every single piece of content in them, even though mouse users don’t have to.
- Semantic
<button>
tags are often not used for actionable elements like the previous, next, and slide dot controls, so keyboard and screen reader users often aren’t able to reach, understand, and activate them. - Inaccessible icons are often used, usually without human-readable accessible names, which can make controls unusable for screen reader and voice input users.
- If the carousel automatically advances, keyboard and screen reader users can be constantly tossed around in the DOM, unable to make sense of the content that keeps shifting in front of them. Auto-rotation can also be very distracting and disruptive for people with cognitive conditions that affect their attention or memory.
- Sometimes carousels come with hidden keyboard commands, like using the arrow keys to move between slides. But since carousel implementations are not really standardized, these commands will really just confuse real keyboard users, since there is really no reason to expect them to be there.
Key elements of an accessible carousel
At the moment, there is nothing in the HTML specification that really resembles a carousel, so defining how an accessible carousel “should” be built is tricky. The W3C’s WAI-ARIA Working Group has provided a design pattern in their WAI-ARIA Authoring Practices 1.1 guide with some good guidance, but the group has also published a tutorial with some different guidance, which tends to be a bit confusing if you aren’t deeply involved in the accessibility scene. (Hopefully this’ll improve, though! See issues #594 and #1167)
At Accessible360, our team of expert accessibility auditors, which includes native screen reader, keyboard, and other AT users, has been carefully crafting and iteratively refining a practical approach to carousels that we use to guide our clients towards WCAG conformance in a clear, consistent way. The approach that we’ve developed has a lot in common with this example from the WAI-ARIA Authoring Practices design pattern, and uses the following criteria:
- Use the
<section>
tag (orrole="region"
) with a genericaria-label
(likearia-label="hero carousel"
) for the wrapper element so screen reader users know exactly where the carousel starts and ends in the DOM. - Add simple instructions for screen reader users to explain how the carousel is set up and how it works. This isn’t required for WCAG conformance, but until carousels become more standardized, instructions can help screen reader users build up a useful mental model.
- When a slide is not visible on the screen, it should be hidden from all users either using CSS (like
display: none
orvisibility: hidden
), the HTMLhidden
attribute, or by addingaria-hidden="true"
to the slide’s wrapper andtabindex="-1"
to all the focusable elements inside it. FYI — that last technique is the most animation-friendly. - Avoid using list markup for the slides. Screen readers announce how many list items are in each list, but ignores list items that are hidden. If you are truly hiding the slides that aren’t visible (see previous point), then the number of list items announced to a user won’t match the true number of slides. Also, most screen readers don’t tell users which list item they are currently on, or when they enter or exit one (the next point will cover that!), so this markup isn’t especially useful in this use case.
- Use
role="group"
and a numberedaria-label
(likearia-label="slide 1 of 8"
) on the wrapper of each individual slide so screen reader users can easily tell where each slide begins and ends and where they are in the set. - Use semantic button elements with clear accessible names for all interactive controls, like the previous/next buttons and slide navigation dots.
- Use
aria-current="true"
on the button of the slide dot corresponding to the currently-active slide so that screen reader users are informed. - Don’t use custom keyboard controls, like arrow keys for navigation. These just confuse real keyboard users, and are probably going to be missed entirely by screen reader users since they already use their arrow keys for navigating with their virtual cursor.
- Disable autoplay — nobody actually likes it, and for some users this can be an absolute blocker! If you’re not in a position to say “no”, then you can at least minimize the harm by adding a pause or stop button to meet WCAG 2.2.2. But keep in mind, just because something conforms to WCAG doesn’t mean people will actually enjoy using it!
Try it out for yourself!
If you’re like me, nothing beats a live code sample to help really understand a complex component like this. So let’s take a look at what a “good” and “bad” carousel could actually look like, and do a little testing to see how each problem can resolved with the solutions above.
❌ Bad carousel
In this carousel, Murphy’s Law has taken over! Using the criteria above, see if you can spot all the things that are wrong with this. Be sure to use your keyboard and a screen reader, like NVDA or VoiceOver! Here are a few prompts to guide you:
- Can you tell when you enter the carousel and when you leave it using a screen reader?
- Can you reach all the controls with your keyboard?
- Are you able to figure out what each control does based on what your screen reader says?
- Can you reach content in the slides that are supposed to be hidden?
- Can you tell which slide you are on using only your screen reader?
✔️ Good carousel
Now let’s take a look at a carousel that looks and feels exactly the same, but uses more accessible code. Compare it to the “bad carousel” example above, and be sure to also use your keyboard and a screen reader to experience it in different ways!
Accessible boilerplates for common carousel packages
Knowing what makes a carousel “good” or “bad” for accessibility is all well and good, but actually putting that knowledge into practice in the real world might be easier said than done!
In the real world, most of us devs use third-party, open source packages like Slick Slider or Flickity whenever we need a carousel, which adds another layer of complexity that makes it even harder to deliver accessible experiences. Unfortunately, many of these packages have either been abandoned or have communities that are so large and ad-hoc that forward progress is a real challenge.
Luckily, most of these packages provide APIs that you can use to make adjustments for accessibility at specific times, like adding ARIA attributes or using custom elements for controls. But since each API and package is a little bit different, it takes time to read through the developer docs and figure it all out.
Wouldn’t it be great if there was a repository of ready-to-go code snippets for popular carousel packages that you could drop into your project to make them more accessible and save you some time? Well, we thought so too, which is why we’ve been building out a set of consistent code samples for common use cases that you can start using right now! You can get these samples at either of the following places (the samples are the same!):
- Github repo: https://github.com/Accessible360/accessible-carousel-boilerplates
- CodePen collection: https://codepen.io/collection/narjZO
There you’ll find realistic code snippets for hero banners, linked product cards, tiles with quick view popups, and even PDP product images with a carousel of thumbnails. So far, code snippets have been created for accessible-slick, Flickity, Owl Carousel 2, Slick Slider, and Splide. To request snippets for other packages or use cases, feel free to open an issue on the Github repo!
Here is just one of these examples, which uses accessible-slick (a highly accessible Slick Slider fork built by Accessible360) to implement a responsive product tile slider with “quick view” modal dialogs:
Credits
The research and code snippets in this article are provided by Accessible360, whose expert accessibility engineers were invaluable with their insight, feedback, and time on this topic.
If your company is looking for an accessibility partner to help bring your product to the next level through live user audits, monitoring, training, or remediation support, then get in touch today!
Sources
- Auto-Forwarding Carousels and Accordions Annoy Users and Reduce Visibility by Jakob Nielsen via Nielsen Norman Group
- Carousel Usability: Designing an Effective UI for Websites with Content Overload by Kara Pernice via Nielsen Norman Group
- ShouldIUseACarousel.com by Jared Smith
- Accessibility expert warns: stop using carousels. Interview with Jared Smith by Creative Bloq
- The Unbearable Inaccessibility of Slideshows by Gian Wild
- Carousel Interaction Stats by Erik Runyon
Top comments (3)
Thanks for this thought provoking article Jason.
Why do you choose to guide your clients towards the "grouped" carousel implementation pattern of rather than the "tabbed" pattern (cf. w3.org/TR/wai-aria-practices-1.1/#...)?
Also, when activating a slide using the slide picker buttons/dots in your "good carousel" example, you don't set focus to the activated slide (as suggested here w3.org/WAI/tutorials/carousels/fun...). Is there an accessibility reason for not doing this, or it was just out of scope for your article?
Cheers
-- ickers
1) When testing the "tabbed" pattern with live low-vision, blind, and deafblind users at Accessible360, we found that that it was very confusing and unintuitive for them. Specifically:
aria-controls
doesn't really do anything in current-gen screen readers, they would have to deduce that the tabs control the preceding content. Again there were concerns about cognitively impaired users. Anecdotally, the sighted and non-sighted members of the testing team had significant difficulty communicating their frustrations and expectations because of the discrepancies between the visual appearance and the programmatic implementation (meaning the use of terms like "tabs" or "tabpanels" in conversations lead to a lot of confusion).2) Moving a keyboard user's focus programmatically is generally very disruptive, especially with non-native components (like carousels) that don't have established behaviors or clear instructions. The auditors at Accessible360 felt this was a violation of WCAG 3.2.2, which could be remediated with visible instructions, though a more intuitive solution seemed to be to just not move a user's focus. Keep in mind that carousel slides can contain a huge variety of content, some of which may be focusable natively, some not. If the slides were block-level link cards, setting focus to them may not be as strange since a keyboard user would probably have tabbed over them as they were exploring the carousel. But if the slides were wrappers containing multiple interactive elements and static content, the slide wrapper would need
tabindex="-1"
in order to receive focus, and we found that keyboard-only users were very confused about why they could reach those wrappers sometimes (from the slide dots) and not others (tabbing naturally).Thanks for such a detailed examples. But I am trying to understand after a modal closes up in accessible example, I expect the focus comes to the button/link from where it is activated, I could see here, the focus comes out of the carousel Any help is required why it is coded like that.
Thanks.