Skip to content
easeweb
Search topics

Carousels that keyboard and screen reader users can't use

A homepage carousel's arrows and dots take only clicks, or, once they are buttons, still never say which slide is showing or that it changed.

WCAG 2.2
SC 2.1.1ASC 4.1.2A
Required by
Section 508 · EN 301 549 (EU)
Broken <div class="carousel-next"></div>
The accessibility problem illustrated: Tab jumps past the arrows and dots.
01

The problem

Keyboard users can't show any slide but the first, and even once the arrows and dots work, screen reader users aren't told which slide is showing or that it changed.

02

Try it

Show the second slide with Tab, and check that a screen reader would know it is showing.

In Broken 1, Tab skips the arrows and dots. In Broken 2 they work with the keyboard, but watch the panel below: no dot is ever said to be current, and pressing Next or a dot reads nothing of the new slide.

Broken Can you fix this?

Paper and light

Our autumn exhibition, until 31 January.

See the exhibition
Opening times

Screen reader says:

(Tab into the carousel, or click a dot)

A recreated demo. The broken version is intentionally inaccessible.

03

The fix

Make the arrows and dots named buttons, mark the current dot, and read each new slide out.

  1. 1Every arrow and dot is a native button with a name.
  2. 2The current dot is marked with aria-current, and its look is drawn from it.
  3. 3A slide that a button brings in is read out, without moving focus.
Before

Arrows and dots that take only clicks

<div class="carousel">  <div class="slides">    <div class="slide">      <h2>Paper and light</h2>      <p>Our autumn exhibition, until 31 January.</p>      <a href="/exhibitions/paper-and-light">See the exhibition</a>    </div>    <div class="slide" hidden>      <h2>Open late on Fridays</h2>      <p>Galleries and café open until 9 pm.</p>      <a href="/visit">Plan your visit</a>    </div>    <div class="slide" hidden>      <h2>Become a member</h2>      <p>Free entry all year, and a first look at every new show.</p>      <a href="/membership">Join today</a>    </div>  </div>  <div class="carousel-prev"></div>  <div class="carousel-next"></div>  <div class="carousel-dots">    <span class="carousel-dot is-current"></span>    <span class="carousel-dot"></span>    <span class="carousel-dot"></span>  </div></div>
After Arrows and dots as buttons
<section class="carousel" aria-roledescription="carousel" aria-label="Highlights">  <button type="button" class="carousel-prev">    <svg aria-hidden="true" focusable="false"><use href="#icon-previous"></use></svg>    <span class="visually-hidden">Previous slide</span>  </button>  <button type="button" class="carousel-next">    <svg aria-hidden="true" focusable="false"><use href="#icon-next"></use></svg>    <span class="visually-hidden">Next slide</span>  </button>  <div class="slides" aria-live="polite">    <div class="slide" role="group" aria-roledescription="slide" aria-label="1 of 3">      <h2>Paper and light</h2>      <p>Our autumn exhibition, until 31 January.</p>      <a href="/exhibitions/paper-and-light">See the exhibition</a>    </div>    <div class="slide" role="group" aria-roledescription="slide" aria-label="2 of 3" hidden>      <h2>Open late on Fridays</h2>      <p>Galleries and café open until 9 pm.</p>      <a href="/visit">Plan your visit</a>    </div>    <div class="slide" role="group" aria-roledescription="slide" aria-label="3 of 3" hidden>      <h2>Become a member</h2>      <p>Free entry all year, and a first look at every new show.</p>      <a href="/membership">Join today</a>    </div>  </div>  <div class="carousel-dots">    <button type="button" class="carousel-dot" aria-current="true"><span class="visually-hidden">Slide 1</span></button>    <button type="button" class="carousel-dot"><span class="visually-hidden">Slide 2</span></button>    <button type="button" class="carousel-dot"><span class="visually-hidden">Slide 3</span></button>  </div></section>

Why this fix: Use native HTML first

Fixing this with an AI coding assistant? Get this guide as Markdown

04

Verify the fix

4 checks, no mouse.

Test with: Keyboard, Screen reader, Forced colors

0 of 4 checked

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the carousel, its slides or its library change.

Limits

This is a starting pattern, not a guarantee for every application. It covers how the arrows and dots are reached and what they say. A carousel that also turns by itself needs a way to stop it as well (2.2.2): see tickers, carousels and animations that can't be paused, which also covers stopping the rotation when focus enters a slide. The text over each slide still needs enough contrast against its picture (1.4.3), and a slide's picture needs alt text when it carries information.

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

Keep this fixed as your code changes.

Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.

How retests work