创建无障碍轮播界面

发布时间:2025 年 9 月 29 日

无论您喜欢还是讨厌,轮播界面都是一种广泛使用且备受青睐的设计模式。因此,在实现轮播界面时,应确保其稳健性和可访问性。它应在首次绘制时具有互动性,采用声明式结构以便于维护,并采用经过辅助技术测试的语义结构构建。

不过,使轮播界面具有无障碍功能通常是一项艰巨的任务。管理焦点、正确获取屏幕阅读器公告以及处理屏幕外互动元素非常复杂,因此许多网站上的轮播界面都无法访问。这些挑战促使 Chrome 团队着手开发交互式 CSS 轮播界面,作为 CSS 溢出模块级别 5 的一部分,该模块已在 Chrome 135 中发布。

在 Chrome 中首次推出该功能后,我们收到了许多社区反馈,并一直在努力解决相关问题。这包括新功能,例如支持离散和导航滚动标记模式,以及多项 bug 修复。 例如:

我们认为,CSS Overflow 5 中的功能可以创建在首次绘制时就具有交互性的强大且易于访问的轮播界面。本文将引导您完成相关操作,重点介绍如何使用这些功能来解决长期存在的无障碍问题。

如需更全面地了解轮播界面,请参阅使用 CSS 实现轮播界面一文。请注意:没有任何界面可以保证开箱即用,您始终需要测试网页的无障碍功能。

在开始编写代码之前,请务必了解您要构建哪种轮播界面。合适的无障碍策略取决于用户应如何体验内容。这篇博文涵盖了三种常见类型:

单项轮播界面

一个轮播界面,屏幕上显示一项内容,并带有用于选择其他内容的标记。

对于单项轮播界面,一次只能完全显示并互动一个幻灯片(例如,主横幅或幻灯片)。

自动分页的轮播界面

同时显示多个幻灯片的轮播界面。

自动分页轮播界面会显示内容“页面”,例如产品列表或电视节目列表。

多项轮播界面

在多项轮播界面中,轮播界面中的多项内容会同时显示,但您仍然可以单独滚动浏览这些内容,而无需分页。

每种类型的轮播界面都有不同的无障碍考虑因素和最佳实践。

单项轮播界面

这是经典幻灯片。虽然在许多情况下,用户会看到下一个或上一个项目的“预览”,以提供有关其他内容的背景信息,但一次只能读取一个子元素。目的是确保只有居中且完全可见的幻灯片可供互动。

下面将逐步介绍如何使其可供访问。

第 1 步:通过滚动吸附强制实现单一焦点

为确保滚动容器始终“贴靠”到某个幻灯片,不会有任何项尴尬地卡在中间,请使用 CSS 滚动贴靠。这样可确保在滚动后,商品能够完美“贴合”到正确位置,从而打造流畅的用户体验。

.carousel {
  scroll-snap-type: inline mandatory;
}
.item {
  scroll-snap-align: center;
}

使用屏幕阅读器的用户需要知道自己已进入轮播界面,以及轮播界面中的幻灯片何时发生变化。这需要在轮播容器上添加一些 ARIA 属性:


ARIA 属性

说明

role="region"

将轮播界面标识为网页上的地标区域,以便更轻松地导航到该区域。

aria-label

为区域提供一个描述性名称,例如“精选商品幻灯片”。

aria-live="polite"

这是神奇的配料。它会指示屏幕阅读器礼貌地宣布此区域内的更改(例如当新幻灯片滚动到视图中时),而不会打断用户。

HTML 结构如下:

<div class="carousel" role="region" aria-label="Slideshow" aria-live="polite"> ... </div>

第 3 步:仅使可见的幻灯片可交互

这对于无障碍功能至关重要,因为它可以防止用户意外跳到屏幕外幻灯片上的按钮或链接。为此,请使用新的 scroll-state 容器查询和 interactivity 属性。

首先,使用 interactivity: inert 默认使每个幻灯片项处于非活动状态。然后,使用 scroll-state 容器查询来定位当前在视口中“贴靠”的幻灯片,并将其内容设置为 interactivity: auto

.item {
  container-type: scroll-state;
}
/* Make all content inside slides inert by default */
.item > * {
  interactivity: inert;
  /* When a slide is snapped inline, make its content interactive */
  @container scroll-state(snapped: inline) {
    > .content {
      interactivity: auto;
    }
  }
}

借助此 CSS,浏览器会自动处理哪些项可聚焦。无需再使用 JavaScript 来管理 tabindex。scroll-state 查询会使除当前幻灯片之外的所有幻灯片处于非活动状态。

分页轮播界面

此模式通常用于将内容分组到页面中的产品或选项库。您可以采用两种方式来处理无障碍功能,具体取决于您希望如何呈现内容。

使用包含 role="region" 的容器,该容器包含一个带有 role="tabpanel" 的元素。此 tabpanel 将更新其内容以反映有效标签页或页面。

<div role="region" class="carousel" aria-label="Featured Products Carousel">
    <div role="tabpanel">
        <div class="item">Item 1</div>
        <div class="item">Item 2</div>
        ...
        <div class="item">Item n</div> </div>
    </div>
</div>

如需管理互动性,请使用与 view() 时间轴相关联的巧妙动画技巧。这样可确保标签页顺序仅到达屏幕上当前可见的项目。

@keyframes interactive-when-visible {
  0% { interactivity: auto; }
}
.item {
  interactivity: inert;
  animation: interactive-when-visible steps(1);
  animation-timeline: view(inline);
}

内容列表

如果内容从根本上来说是一个列表,请使用 <ul> 元素来实现正确的语义

例如:

<div class="carousel" role="region" aria-label="Related Posts">
  <ul>
    <li><!-- Post 1 content --></li>
    <li><!-- Post 2 content --></li>
    <li><!-- Post 3 content --></li>
    <!-- ... -->
  </ul>
</div>

对于此模式,请勿使用互动性属性来使屏幕外内容处于非活动状态。这样做会影响屏幕阅读器播报的项目数量,因此所有内容都必须保留在辅助功能树中。

多项轮播界面

此模式适用于多个子元素可同时显示和读取的轮播界面。例如,电子商务网站上的“相关商品”搁架。

这些轮播界面的行为因您对以下问题的回答而异:您是否要引导用户一次只关注一个项目,还是允许用户随意访问所有可见内容?

模式 1:可见项中包含单个互动项

在此模型中,多个项可见,但只有主要项或“当前”项可互动。其他可见项处于非活动状态。此模式有助于引导用户逐个浏览一组项目。

为了正确构建此轮播界面,您应使用与前面讨论的单项轮播界面相同的无障碍功能模式。这些行为包括:

  • 使用滚动状态容器查询来应用互动性:将非活跃项设为不活跃。
  • 在商品周围添加足够的内边距,以确保每个商品都能贴靠到主要位置(例如,滚动窗口的中心)。这样一来,逐个导航模型就会显得有意为之且流畅自然。

模式 2:所有可见项均可互动

如果您的目标是允许用户自由地与所有可见项互动,那么最佳实践是确保所有内容都不是惰性的。

对于此模式:

  • 如果内容在语义上是列表,请使用 <ul> 元素,因为这样可以为屏幕阅读器用户提供正确的上下文。
  • 请勿使用互动管理 (interactivity: inert)。所有可见内容都应保留在无障碍功能树中,并且可以使用键盘 Tab 键到达。

总结

借助 CSS Overflow 5,您可以声明式地构建常见的互动式轮播界面模式,而无需担心太多无障碍功能问题。通过结合使用语义 HTML、滚动状态和互动性等现代 CSS 以及合适的 ARIA 角色,您可以打造高性能、无障碍的体验,并在首次绘制时实现互动。

不妨试用一下这些新的 API!不过,虽然这些模式和 API 旨在简化构建互动式、快速且易于访问的组件的过程,但它们始终无法取代全面的无障碍功能测试。您始终需要验证代码是否可访问,以及是否适用于您的基准目标平台。