
Accessibility
18.05.2026
ARIA Roles for Accessible Carousels: Explaining role=region and role=group
Lucas Falkowsky
Fullstack Development
A carousel without ARIA markup looks the same as one with it—but to screen reader users, it’s just a jumbled mess of code. This section shows which three attributes are most commonly missing, what NVDA, JAWS, and VoiceOver output without them, and what the correct landmark structure looks like.
Screen readers like NVDA don't read websites visually — they read the markup. And that markup is far too often not designed for users who have text read aloud to them. What gets read out depends almost entirely on what's in the code. If the semantics are missing, so is the context. Users are left to navigate blind.
The carousel is a textbook example of this. Visually, it's immediately clear what it is and how it works. Semantically, without the right ARIA attributes, it's an unsorted heap of code. This section shows which attributes are most often forgotten — and what happens when they're in place.
Why a Carousel Without role="region" Is Invisible to Screen Readers
Screen readers offer their users a feature hidden from sighted users: landmark navigation. NVDA jumps to the next region with R, JAWS with ;, VoiceOver opens a rotor over all landmarks on the page with VO+U. Landmarks are structural elements that divide a web page into logical sections, allowing users to skim the page and decide what to read and what to skip.
A carousel without a landmark is invisible to this navigation. Users have to arrow-key through every single piece of slide content, with no indication that they're inside a cohesive component. That's the first and most common mistake.
The fix is a single attribute:
<!-- ❌ Common mistake: no landmark, no label -->
<div class="carousel">...</div>
<!-- ✅ How to do it -->
<div role="region" aria-roledescription="Carousel" aria-label="Most Popular Products">
<!-- Slides -->
</div>
role="region" turns the container into a navigable landmark — a signpost available for navigation. aria-roledescription overrides the generic role name "Region" with a descriptive term like "Carousel". aria-label gives the landmark a name; without one, some screen readers will even ignore the landmark.
One important detail: the word "carousel" does not belong in aria-label. Since aria-roledescription already announces the type, a label like "Product Carousel" would result in redundant output: "Product Carousel, Carousel." The label names the content; the roledescription names the type.
How role="group" and aria-label Give Screen Readers Context
Even with the container correctly marked up, a common problem remains: individual slides are indistinguishable to screen readers. No context, no position, no total count.
Each slide needs its own semantic identity:
<div role="group" aria-roledescription="Slide" aria-label="3 of 8">
<!-- Slide content -->
</div>
role="group" marks content as a cohesive unit that is not included in the page summary. aria-roledescription="Slide" gives it a descriptive type. aria-label="3 of 8" provides position and total count — the only information that tells users where they are in the carousel and how much is left.
The result is clear, consistent screen reader output on every slide change:
| Screen Reader | Output when navigating |
|---|---|
| NVDA | "Most Popular Products, Carousel, Region" → "3 of 8, Slide" |
| JAWS | "Most Popular Products, Carousel Region" → "3 of 8, Slide" |
| VoiceOver | "Most Popular Products, Carousel" → "3 of 8, Slide" |
Without these attributes, an NVDA user navigating the carousel will simply hear: "Group" — or nothing at all.
When the Tab Pattern Is the Better Choice
The W3C APG describes a second variant alongside the Region Pattern: tab-based slides. Here, a slide picker — often implemented as dot navigation — takes on the role of tab navigation. tablist declares an element as the container for a group of tabs; tabpanel marks a page within a tab list.
<div role="tablist" aria-label="Product Slides">
<button role="tab" aria-selected="true" aria-label="Slide 1">●</button>
<button role="tab" aria-selected="false" aria-label="Slide 2">○</button>
</div>
<div role="tabpanel" aria-label="Slide 1">
<!-- Slide content -->
</div>
Advantage: Keyboard users already know the tab pattern. ArrowLeft and ArrowRight switch between tabs; Tab exits the list. It's an established interaction model, not a new convention to learn.
Disadvantage: It only works when a slide picker is present. A carousel without visible dot or thumbnail navigation should stick to the Region Pattern.
| Criterion | Region Pattern | Tab Pattern |
|---|---|---|
| Dot navigation required? | Not required | Required |
| Familiar keyboard conventions? | No (custom navigation) | Yes (arrow keys) |
| Complexity | Lower | Higher |
What This Means in Practice
Semantics are invisible — which is precisely why they're so often forgotten. A carousel without role="region" and without slide labels looks exactly the same as one with them. No visual test will catch the problem. No screenshot-based audit will flag it.
It only becomes apparent when navigating the page with a screen reader. At that point, the difference between a well-structured and a poorly structured component is the difference between orientation and disorientation.
That's the core of this error — and the reason it so often goes undetected.
What's Coming Next
Semantics are the foundation. But a correctly marked-up component still isn't operable if keyboard users can't access the navigation, or if focus jumps to unexpected places on slide changes.
Part 3 addresses exactly that: keyboard navigation, focus management, and the inert attribute — the often-overlooked mechanism that removes off-screen slides from the accessibility tree.
➔ Keyboard & Focus Management: Self-Determination as a Design Principle
Quellen: W3C APG, Carousel Pattern · W3C APG, Carousel with Tabs · WCAG 2.2
Contact
Got questions about your website's accessibility?
Lucas Falkowsky
Fullstack Development
