Skip to main content

Carousel

SeveritySerious
Accessibility PrincipleOperable
Affected usersVisual, Motor
Success criterion2.3.3

A carousel displays a series of items one at a time, where users swipe left or right to move between them. For screen reader users, the standard swipe gesture conflicts with how they navigate the screen — so a carousel must expose increment and decrement accessibility actions instead, using the adjustable role to signal this to the screen reader.

Expectations

Assistive Technology: Screen Reader
  • When: The user focuses a Carousel component
    • Then: The Screen Reader announces: [Component label] Adjustable/Slider, swipe up or down to adjust
      • When: User swipes up
        • Then: The previous item is focused
      • When: User swipes down
        • Then: The next item is focused
VoiceOverTalkback
[Component label], Adjustable, swipe up or down with one finger to adjust the value[Component label], Slider, swipe up or swipe down to adjust

When the Screen Reader is activated, navigation typically relies on specific gestures to interact with content:

  • 1-finger swipe up: This gesture usually focuses on the next item
  • 1-finger swipe down: This gesture focuses on the previous item

Assistive Technology: Voice Control
  • When: The user pronounces the carousel label
    • Then: Voice Control highlights the carousel
      • And:
          The user can then issue swipe gestures verbally ("swipe left", "swipe right") to advance between items

Example

To implement this navigation behavior in React Native when the Screen Reader is on, we need to:

  • use the accessibility role adjustable
  • set accessibilityActions={[{ name: 'increment' }, { name: 'decrement' }]}
  • handle onAccessibilityAction to change the index
<FlatList
ref={flatList}
data={data}
renderItem={renderItem}
accessible={true}
accessibilityLabel="Carousel"
accessibilityRole="adjustable"
accessibilityActions={[{ name: 'increment' }, { name: 'decrement' }]}
onAccessibilityAction={(event: AccessibilityActionEvent) => {
const value = event.nativeEvent.actionName === 'increment' ? 1 : -1;
const newIndex = carouselIndexForScreenReader.current + value;

carouselIndexForScreenReader.current = clamp(newIndex, 0, data.length - 1);
flatList.current?.scrollToIndex({
index: carouselIndexForScreenReader.current,
});
}}
/>

Best Practices

Use the adjustable role with increment/decrement actions

The adjustable role tells the screen reader that swipe-up/down adjusts a value. Without it, the user has no indication that the carousel can be navigated at all.

accessibilityRole="adjustable"
accessibilityActions={[{ name: 'increment' }, { name: 'decrement' }]}

Announce the current position

Include the item's position in its label or hint so the user knows where they are in the sequence.

accessibilityLabel={`Carousel, item ${currentIndex + 1} of ${data.length}`}

Provide a way to pause auto-advancing carousels

If the carousel advances automatically, include a pause or stop control. Auto-advancing content that cannot be paused fails WCAG 2.2.2 Pause, Stop, Hide.