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.