Make accessible carousels  |  Blog  |  Chrome for Developers
Blog

Make accessible carousels  |  Blog  |  Chrome for Developers

2026.03.25
·Web·by 이호민
#Accessibility#Carousel#CSS#Frontend#Web Development

Key Points

  • 1This paper details how new features in Chrome's CSS Overflow Module Level 5, such as `scroll-state` and `interactivity`, enable the creation of robust and accessible carousels.
  • 2It provides step-by-step guidance on implementing accessible solutions for single-item, paginated, and multi-item carousels, addressing common issues like focus management and screen reader announcements.
  • 3By leveraging semantic HTML, ARIA, and these modern CSS properties, developers can build high-performance and interactive carousels that enhance user experience, emphasizing the ongoing need for thorough accessibility testing.

The paper details how to build robust, accessible, and high-performance carousels using new features from the CSS Overflow Module Level 5, which shipped in Chrome 135 and was further refined in Chrome 140. It addresses the common accessibility challenges of carousels, such as managing focus, ensuring correct screen reader announcements, and handling off-screen interactive elements, often inadequately managed with traditional JavaScript solutions. The core methodology leverages new CSS properties, specifically interactivity and scroll-state container queries, in conjunction with semantic HTML and appropriate ARIA attributes.

The paper categorizes carousels into three main types, each with tailored accessibility strategies:

  1. Single-item Carousels:
    • Description: Only one slide is fully visible and interactive at a time, often used for slideshows or hero banners.
    • Core Methodology:
      • Scroll Snapping: CSS scroll-snap-type: inline mandatory; on the scroll container and scroll-snap-align: center; on child items are used to ensure that only one item is perfectly aligned and fully visible after a scroll operation, creating a clean user experience. This is a foundational step for managing the visual state.
      • Screen Reader Announcements: The carousel container is semantically marked with role="region"role="region" and arialabel="Slideshow"aria-label="Slideshow" to define it as a navigable landmark region. Crucially, arialive="polite"aria-live="polite" is applied to this container. This ARIA live region ensures that screen readers politely announce changes within the carousel, such as a new slide entering the viewport, without interrupting the user's current task.
      • Interactive Focus Management: This is the most significant technical advancement. All slide items are initially rendered inert by default using the CSS property interactivity: inert; applied to their child content (e.g., .item>interactivity:inert;.item > * { interactivity: inert; }). A scroll-state container query is then employed to dynamically re-enable interactivity only for the slide currently "snapped" into the viewport. Specifically, @containerscrollstate(snapped:inline)>.contentinteractivity:auto;@container scroll-state(snapped: inline) { > .content { interactivity: auto; } } makes the content of the snapped slide interactive. This declarative CSS approach automatically handles which elements are focusable, eliminating the need for complex JavaScript-based tabindex manipulation for off-screen elements.
  1. Automatically Paginated Carousels:
    • Description: Content is grouped into "pages," like product galleries.
    • Core Methodology: Two distinct approaches are presented:
      • Carousel with Discrete Pages: A container with role="region"role="region" encapsulates a single role="tabpanel"role="tabpanel". This tabpanel dynamically updates its content to reflect the active page. Unlike single-item carousels, arialive="polite"aria-live="polite" is explicitly *avoided* here to prevent a noisy experience if a user scrolls slowly, as individual items entering the viewport would be announced. Interactivity is managed by tying the interactivity: auto; state to the view() timeline via a CSS animation:
css@keyframes interactive-when-visible { 0% { interactivity: auto; } } .item { interactivity: inert; animation: interactive-when-visible steps(1); animation-timeline: view(inline); }

This ensures that only currently visible items become interactive, aligning the tab order with the visual state.
  • List of Contents: If the content is fundamentally a list, a <ul><ul> element is used for correct semantics (e.g., <divrole="region"><ul/></div><div role="region"><ul /></div>). For this pattern, the interactivity property is *not* used to make off-screen content inert, as doing so would affect the item count announced by screen readers. All content must remain in the accessibility tree and be reachable, adhering to the expectation of a standard list structure.
  1. Multi-item Carousels:
    • Description: Multiple child elements are visible and readable simultaneously, such as a "related products" shelf.
    • Core Methodology: This type depends on the intended user interaction:
      • Single Interactive Item Among Visible Items: Multiple items are visible, but only a designated "primary" or "current" item is interactive. This guides the user's focus sequentially. The implementation reuses the same accessibility pattern as the single-item carousel: interactivity: inert; for non-active items and scroll-state container queries to activate the primary item. Sufficient padding around items is crucial to allow each item to snap to the primary position.
      • All Visible Items Are Interactive: The goal is to allow users to freely interact with all currently visible items. For this, a <ul><ul> element is recommended for semantic correctness if the content is a list. Crucially, no interactivity management (i.e., interactivity: inert;) is applied. All visible content remains in the accessibility tree and is reachable via keyboard tabbing, respecting the user's expectation of direct interaction with all presented elements.

The paper emphasizes that while these new APIs (like interactivity, scroll-state, ::scroll-marker, ::scroll-button, and scroll-snap) simplify building accessible components, comprehensive accessibility testing remains indispensable to verify compliance with target Baselines and ensure a truly inclusive user experience. The planned scroll-marker-group type support is mentioned as a future enhancement that will further automate appropriate roles and semantics.