普通视图

发现新文章,点击刷新页面。
昨天 — 2026年3月30日首页

构建无障碍组件之Carousel Pattern

作者 anOnion
2026年3月30日 23:16

Carousel Pattern 详解:构建无障碍轮播组件

轮播(Carousel)是一种按顺序展示一组内容项(称为幻灯片)的组件。本文基于 W3C WAI-ARIA Carousel Pattern 规范,详解如何构建无障碍的轮播组件。

一、Carousel 的定义与核心概念

1.1 什么是 Carousel

Carousel(也称为幻灯片或图片轮播器)具有以下特征:

  • 展示一组称为**幻灯片(Slide)**的内容项
  • 通常一次显示一个幻灯片,通过控制按钮切换
  • 可以自动轮播,也可以手动控制
  • 幻灯片可以包含任何类型的内容,图片轮播最为常见

1.2 核心术语

术语 说明
Slide 轮播中的单个内容容器
Rotation Control 停止/启动自动轮播的交互控件
Next Slide Control 显示下一张幻灯片的控件(通常为箭头样式)
Previous Slide Control 显示上一张幻灯片的控件(通常为箭头样式)
Slide Picker Controls 选择特定幻灯片的控件组(通常为圆点样式)
┌─────────────────────────────────────────────────────────────┐
│  Carousel (role="region" + aria-roledescription)            │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐    │
│  │                                                     │    │
│  │              ┌─────────────────┐                    │    │
│  │              │    Slide 1      │                    │    │
│  │              │  ┌───────────┐  │                    │    │
│  │              │  │           │  │                    │    │
│  │              │  │  Image /  │  │  <-- Current       │    │
│  │              │  │  Content  │  │      Slide         │    │
│  │              │  │           │  │                    │    │
│  │              │  └───────────┘  │                    │    │
│  │              └─────────────────┘                    │    │
│  │                                                     │    │
│  │  ┌─────────────────────────────────────────────┐    │    │
│  │  │  Slide 2 (hidden)    │   Slide 3 (hidden)   │    │    │
│  │  └─────────────────────────────────────────────┘    │    │
│  │                                                     │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│     <-- Prev        o O O        Next -->                   │
│           (Slide Picker / Dots Navigation)                  │
│                                                             │
│                    [ Pause/Play ]                           │
└─────────────────────────────────────────────────────────────┘

1.3 无障碍挑战

轮播组件如果没有正确实现,会对无障碍体验造成严重影响:

  • 屏幕阅读器用户困惑:如果不可见的幻灯片没有被正确隐藏,用户可能在不知情的情况下从幻灯片 1 跳转到幻灯片 2 的内容
  • 自动轮播干扰:自动轮播可能打断屏幕阅读器用户的浏览流程
  • 键盘导航困难:如果轮播没有正确处理焦点管理,键盘用户可能无法有效控制轮播

二、WAI-ARIA 角色与属性

2.1 基本角色

轮播区域使用 role="region" 标记为地标区域,并通过 aria-roledescription="carousel" 提供额外的角色描述:

<section
  role="region"
  aria-roledescription="carousel"
  aria-label="产品展示">
  <!-- 轮播内容 -->
</section>

2.2 幻灯片属性

每个幻灯片具有以下属性:

<div
  role="group"
  aria-roledescription="slide"
  aria-label="第 1 张,共 3 张">
  <!-- 幻灯片内容 -->
</div>

2.3 幻灯片可见性

使用 aria-hidden 控制幻灯片的可见性:

  • aria-hidden="true":幻灯片不可见(不在视口内)
  • aria-hidden="false":幻灯片可见(当前显示的幻灯片)
<!-- 当前显示的幻灯片 -->
<div
  role="group"
  aria-roledescription="slide"
  aria-label="第 1 张,共 3 张"
  aria-hidden="false">
  <img
    src="slide1.jpg"
    alt="产品图片 1" />
</div>

<!-- 隐藏的幻灯片 -->
<div
  role="group"
  aria-roledescription="slide"
  aria-label="第 2 张,共 3 张"
  aria-hidden="true">
  <img
    src="slide2.jpg"
    alt="产品图片 2" />
</div>

2.4 控制按钮属性

上一张/下一张按钮

使用 aria-controls 属性指向被控制的幻灯片容器 ID,让辅助技术用户了解按钮会影响哪个区域的内容:

<button
  aria-label="上一张"
  aria-controls="carousel-slides"></button>
<button
  aria-label="下一张"
  aria-controls="carousel-slides"></button>
轮播控制按钮(停止/启动)

使用 aria-pressed 表示按钮的按下状态,false 表示轮播正在运行,点击后会停止:

<button
  aria-label="停止轮播"
  aria-pressed="false"
  aria-controls="carousel-slides"></button>
幻灯片选择器(圆点导航)

幻灯片选择器使用 role="tab" 模式,每个圆点按钮都是一个 tab,通过 aria-selected 表示当前选中的幻灯片:

<div
  role="tablist"
  aria-label="幻灯片选择">
  <button
    role="tab"
    aria-label="第 1 张"
    aria-selected="true"
    aria-controls="slide-1"></button>
  <button
    role="tab"
    aria-label="第 2 张"
    aria-selected="false"
    aria-controls="slide-2"></button>
  <button
    role="tab"
    aria-label="第 3 张"
    aria-selected="false"
    aria-controls="slide-3"></button>
</div>

三、键盘交互规范

3.1 基本键盘交互

按键 功能
Tab / Shift + Tab 在轮播的交互元素之间移动焦点
Space / Enter 激活按钮(上一张、下一张、停止/启动)
方向键(可选) 如果幻灯片选择器使用 Tab 模式,可用方向键切换幻灯片

3.2 自动轮播的键盘行为

  • 当轮播中的任何元素获得键盘焦点时,自动轮播必须停止
  • 轮播不会自动恢复,除非用户明确激活旋转控制

3.3 Tab 顺序

  • 旋转控制按钮(如果存在)必须是轮播内部 Tab 顺序中的第一个元素
  • 这确保辅助技术用户可以轻松找到控制按钮

四、鼠标交互规范

4.1 悬停行为

  • 当鼠标悬停在轮播上时,自动轮播必须停止
  • 鼠标移出后,可以恢复自动轮播(根据设计决定)

4.2 点击行为

  • 点击上一张/下一张按钮切换幻灯片
  • 点击幻灯片选择器跳转到特定幻灯片
  • 点击旋转控制按钮停止/启动自动轮播

五、实现方式

5.1 基础轮播结构

<section
  class="carousel"
  aria-roledescription="carousel"
  aria-label="产品展示">
  <!-- 旋转控制按钮 -->
  <button
    class="rotation-control"
    aria-label="停止轮播"
    aria-pressed="false"
    aria-controls="carousel-slides"></button>

  <!-- 幻灯片容器 -->
  <div
    id="carousel-slides"
    class="carousel-slides">
    <div
      role="group"
      aria-roledescription="slide"
      aria-label="第 1 张,共 3 张"
      aria-hidden="false"
      class="slide active">
      <img
        src="slide1.jpg"
        alt="产品图片 1" />
      <div class="slide-content">
        <h2>产品标题 1</h2>
        <p>产品描述...</p>
        <a href="/product1">了解更多</a>
      </div>
    </div>

    <div
      role="group"
      aria-roledescription="slide"
      aria-label="第 2 张,共 3 张"
      aria-hidden="true"
      class="slide">
      <img
        src="slide2.jpg"
        alt="产品图片 2" />
      <div class="slide-content">
        <h2>产品标题 2</h2>
        <p>产品描述...</p>
        <a href="/product2">了解更多</a>
      </div>
    </div>

    <div
      role="group"
      aria-roledescription="slide"
      aria-label="第 3 张,共 3 张"
      aria-hidden="true"
      class="slide">
      <img
        src="slide3.jpg"
        alt="产品图片 3" />
      <div class="slide-content">
        <h2>产品标题 3</h2>
        <p>产品描述...</p>
        <a href="/product3">了解更多</a>
      </div>
    </div>
  </div>

  <!-- 导航按钮 -->
  <button
    class="prev-btn"
    aria-label="上一张"
    aria-controls="carousel-slides"></button>
  <button
    class="next-btn"
    aria-label="下一张"
    aria-controls="carousel-slides"></button>

  <!-- 幻灯片选择器 -->
  <div
    class="slide-picker"
    role="tablist"
    aria-label="幻灯片选择">
    <button
      role="tab"
      aria-label="第 1 张"
      aria-selected="true"
      aria-controls="slide-1"></button>
    <button
      role="tab"
      aria-label="第 2 张"
      aria-selected="false"
      aria-controls="slide-2"></button>
    <button
      role="tab"
      aria-label="第 3 张"
      aria-selected="false"
      aria-controls="slide-3"></button>
  </div>
</section>

5.2 关键实现要点

幻灯片可见性管理:

  • 当前显示的幻灯片:aria-hidden="false"
  • 隐藏的幻灯片:aria-hidden="true"
  • 使用 CSS 控制显示/隐藏(如 opacitydisplayvisibility

自动轮播控制:

  • 键盘焦点进入轮播区域时,必须停止自动轮播
  • 鼠标悬停在轮播上时,必须停止自动轮播
  • 提供停止/启动按钮,让用户控制自动轮播

幻灯片选择器状态:

  • 当前幻灯片对应的按钮:aria-selected="true"
  • 其他按钮:aria-selected="false"

六、常见应用场景

6.1 产品图片展示

<section
  aria-roledescription="carousel"
  aria-label="产品图片">
  <div
    role="group"
    aria-roledescription="slide"
    aria-label="第 1 张,共 4 张">
    <img
      src="product-1.jpg"
      alt="产品正面视图" />
  </div>
  <div
    role="group"
    aria-roledescription="slide"
    aria-label="第 2 张,共 4 张">
    <img
      src="product-2.jpg"
      alt="产品侧面视图" />
  </div>
  <div
    role="group"
    aria-roledescription="slide"
    aria-label="第 3 张,共 4 张">
    <img
      src="product-3.jpg"
      alt="产品背面视图" />
  </div>
  <div
    role="group"
    aria-roledescription="slide"
    aria-label="第 4 张,共 4 张">
    <img
      src="product-4.jpg"
      alt="产品细节视图" />
  </div>
</section>

6.2 testimonials/客户评价

<section
  aria-roledescription="carousel"
  aria-label="客户评价">
  <div
    role="group"
    aria-roledescription="slide"
    aria-label="第 1 张,共 3 张">
    <blockquote>
      <p>"这个产品改变了我的工作方式..."</p>
      <footer>— 张三,某公司员工</footer>
    </blockquote>
  </div>
  <div
    role="group"
    aria-roledescription="slide"
    aria-label="第 2 张,共 3 张">
    <blockquote>
      <p>"客服非常专业,响应迅速..."</p>
      <footer>— 李四,自由职业者</footer>
    </blockquote>
  </div>
</section>

6.3 新闻/公告轮播

<section
  aria-roledescription="carousel"
  aria-label="最新公告">
  <div
    role="group"
    aria-roledescription="slide"
    aria-label="第 1 张,共 3 张">
    <article>
      <h3>公司发布新产品</h3>
      <p>我们很高兴地宣布...</p>
      <a href="/news/1">阅读更多</a>
    </article>
  </div>
</section>

七、最佳实践

7.1 始终提供轮播控制

  • 必须提供上一张/下一张按钮
  • 如果启用自动轮播,必须提供停止/启动控制按钮
  • 建议提供幻灯片选择器(圆点导航)

7.2 正确处理幻灯片可见性

  • 使用 aria-hidden="true" 隐藏不可见的幻灯片
  • 确保隐藏的幻灯片内容不会被屏幕阅读器读取
  • 当前幻灯片使用 aria-hidden="false"

7.3 自动轮播的控制

  • 自动轮播必须在以下情况下停止:
    • 键盘焦点进入轮播区域
    • 鼠标悬停在轮播上
    • 用户点击停止按钮
  • 不要在用户未明确请求的情况下重新启动自动轮播

7.4 提供清晰的标签

  • 为轮播区域提供描述性的 aria-label
  • 为每个幻灯片提供包含位置信息的标签(如"第 1 张,共 3 张")
  • 为所有控制按钮提供清晰的 aria-label

7.5 避免使用轮播的情况

以下情况不建议使用轮播:

  • 内容对用户都很重要,需要同时可见
  • 用户需要比较不同幻灯片的内容
  • 幻灯片内容包含重要的交互元素

在这些情况下,考虑使用静态列表或网格布局。

7.6 移动端触摸支持

移动端应支持触摸滑动切换幻灯片:

  • 向左滑动 → 显示下一张
  • 向右滑动 → 显示上一张
  • 需要设置滑动阈值(如 50px),避免误触

八、总结

构建无障碍的 Carousel 组件需要特别关注:

  1. 正确的 ARIA 标记:使用 role="region"aria-roledescriptionaria-hidden 等属性
  2. 完整的键盘支持:确保所有功能都可以通过键盘访问
  3. 自动轮播控制:提供停止/启动控制,并在焦点进入时自动停止
  4. 清晰的标签:为轮播、幻灯片和控制按钮提供描述性标签
  5. 幻灯片可见性管理:正确隐藏不可见的幻灯片,避免屏幕阅读器混淆

轮播组件虽然常见,但如果没有正确实现,会对无障碍体验造成严重影响。遵循 W3C Carousel Pattern 规范,我们能够创建既美观又包容的轮播组件,为所有用户提供良好的体验。

文章同步于 an-Onion 的 Github。码字不易,欢迎点赞。

昨天以前首页

构建无障碍组件之Tabs Pattern

作者 anOnion
2026年3月28日 22:31

标签页(Tabs)是一种分层的内容展示组件,通过标签列表(Tab List)和对应的内容面板(Tab Panel)来组织和展示内容。本文基于 W3C WAI-ARIA Tabs Pattern 规范,详解如何构建无障碍的标签页组件。

一、Tabs 的定义与核心概念

1.1 什么是 Tabs

Tabs 是一种将内容分层展示的界面模式:

  • Tab List(标签列表):包含一组标签元素的容器
  • Tab(标签):作为对应内容面板的标签,激活后显示该面板
  • Tab Panel(标签面板):包含与标签关联的内容的元素
  • 通常一次只显示一个标签面板
  • 标签列表通常排列在当前显示面板的边缘(最常见的是顶部)

1.2 核心术语

术语 说明
Tab List 包含在 tablist 元素中的一组标签元素
Tab 标签列表中的元素,作为对应面板的标签
Tab Panel 包含与标签关联内容的元素
┌─────────────────────────────────────────┐
│  Tab List (role="tablist")              │
│  ┌─────────┬─────────┬─────────┐        │
│  │ Tab 1   │ Tab 2   │ Tab 3   │        │
│  │(active) │         │         │        │
│  └────┬────┴─────────┴─────────┘        │
│       │                                 │
│       ▼                                 │
│  ┌─────────────────────────────────┐    │
│  │  Tab Panel 1 (role="tabpanel")  │    │
│  │  ┌─────────────────────────┐    │    │
│  │  │                         │    │    │
│  │  │      Content Panel 1    │    │    │
│  │  │      (currently shown)  │    │    │
│  │  │                         │    │    │
│  │  └─────────────────────────┘    │    │
│  └─────────────────────────────────┘    │
│                                         │
│  ┌─────────────────────────────────┐    │
│  │  Tab Panel 2 (role="tabpanel")  │    │
│  │  ┌─────────────────────────┐    │    │
│  │  │      Content Panel 2    │    │    │
│  │  │      (hidden)           │    │    │
│  │  └─────────────────────────┘    │    │
│  └─────────────────────────────────┘    │
└─────────────────────────────────────────┘

1.3 自动激活 vs 手动激活

Tabs 有两种激活模式:

自动激活(Automatic Activation)

  • 标签获得焦点时自动激活并显示对应面板
  • 要求面板内容已预加载,避免延迟
  • 用户导航更高效

手动激活(Manual Activation)

  • 用户需要按 Space 或 Enter 激活标签
  • 适用于面板内容加载有延迟的场景
  • 避免焦点移动时的不必要加载

二、WAI-ARIA 角色与属性

2.1 基本角色

<div
  role="tablist"
  aria-label="产品信息">
  <button
    role="tab"
    aria-selected="true"
    id="tab-1">
    产品详情
  </button>
  <button
    role="tab"
    aria-selected="false"
    id="tab-2">
    规格参数
  </button>
  <button
    role="tab"
    aria-selected="false"
    id="tab-3">
    用户评价
  </button>
</div>

<div
  role="tabpanel"
  aria-labelledby="tab-1">
  <!-- 产品详情内容 -->
</div>

2.2 Tab List 属性

Tab List 容器具有 role="tablist"

<!-- 水平标签页(默认) -->
<div
  role="tablist"
  aria-label="产品信息">
  ...
</div>

<!-- 垂直标签页 -->
<div
  role="tablist"
  aria-label="设置选项"
  aria-orientation="vertical">
  ...
</div>

2.3 Tab 属性

每个标签具有 role="tab"

<button
  role="tab"
  id="tab-1"
  aria-selected="true"
  aria-controls="panel-1"
  tabindex="0">
  产品详情
</button>

<button
  role="tab"
  id="tab-2"
  aria-selected="false"
  aria-controls="panel-2"
  tabindex="-1">
  规格参数
</button>

2.4 Tab Panel 属性

每个面板具有 role="tabpanel"

  • aria-labelledby:引用对应标签的 ID
  • 未激活的面板通常使用 hidden 属性或 CSS 隐藏
<div
  role="tabpanel"
  id="panel-1"
  aria-labelledby="tab-1">
  <!-- 激活的面板内容 -->
</div>

<div
  role="tabpanel"
  id="panel-2"
  aria-labelledby="tab-2"
  hidden>
  <!-- 未激活的面板内容 -->
</div>

三、键盘交互规范

3.1 Tab 键导航

场景 行为
焦点进入 Tab List 焦点置于当前激活的标签上
焦点在 Tab List 中 焦点移动到 Tab List 外的下一个元素(通常是 Tab Panel 或其内部第一个可聚焦元素)

3.2 方向键导航(水平标签页)

按键 功能
左箭头 焦点移到上一个标签;如果在第一个标签,移到最后一个
右箭头 焦点移到下一个标签;如果在最后一个标签,移到第一个
Home(可选) 焦点移到第一个标签
End(可选) 焦点移到最后一个标签

3.3 方向键导航(垂直标签页)

按键 功能
上箭头 等同于水平标签页的左箭头
下箭头 等同于水平标签页的右箭头

3.4 激活操作

按键 功能
Space / Enter 激活当前聚焦的标签(手动激活模式下)
Shift + F10(Windows)
Control + 点击(Mac)
如果标签有关联的弹出菜单,打开菜单
Delete(可选) 如果允许删除,删除当前标签及其面板

3.5 自动激活说明

  • 推荐在面板内容已预加载时使用自动激活
  • 自动激活时,方向键移动焦点会立即激活对应标签
  • 如果面板加载有延迟,使用手动激活避免阻碍导航

四、实现方式与样式要点

4.1 基础 HTML 结构

<div class="tabs">
  <!-- Tab List -->
  <div
    role="tablist"
    aria-label="产品信息">
    <button
      role="tab"
      id="tab-1"
      aria-selected="true"
      aria-controls="panel-1"
      tabindex="0">
      产品详情
    </button>
    <button
      role="tab"
      id="tab-2"
      aria-selected="false"
      aria-controls="panel-2"
      tabindex="-1">
      规格参数
    </button>
    <button
      role="tab"
      id="tab-3"
      aria-selected="false"
      aria-controls="panel-3"
      tabindex="-1">
      用户评价
    </button>
  </div>

  <!-- Tab Panels -->
  <div
    role="tabpanel"
    id="panel-1"
    aria-labelledby="tab-1">
    <h2>产品详情</h2>
    <p>这是一款高性能的...</p>
  </div>

  <div
    role="tabpanel"
    id="panel-2"
    aria-labelledby="tab-2"
    hidden>
    <h2>规格参数</h2>
    <table>
      <tr>
        <th>尺寸</th>
        <td>100 x 50 x 20 mm</td>
      </tr>
      <tr>
        <th>重量</th>
        <td>200g</td>
      </tr>
    </table>
  </div>

  <div
    role="tabpanel"
    id="panel-3"
    aria-labelledby="tab-3"
    hidden>
    <h2>用户评价</h2>
    <p>"非常满意这款产品..."</p>
  </div>
</div>

4.2 样式实现注意事项

4.2.1 激活状态样式

激活的标签需要有明显的视觉区分:

  • 下划线/边框:使用边框颜色变化指示激活状态
  • 背景色:激活标签使用不同的背景色
  • 文字样式:加粗或改变颜色增强对比

4.2.2 焦点状态样式

确保键盘用户可以清楚看到当前焦点位置:

  • 使用 outlinebox-shadow 创建焦点环
  • 焦点环颜色与背景有足够对比度
  • 避免使用 outline: none 而不提供替代样式

4.2.3 面板显示/隐藏

  • 未激活的面板应使用 hidden 属性或 display: none 完全隐藏
  • 避免使用 visibility: hiddenopacity: 0,这会让内容仍可被屏幕阅读器访问

4.2.4 垂直标签页样式

垂直布局时需要注意:

  • 标签列表使用 flex-direction: column
  • 激活指示器从底部边框改为右侧边框
  • 确保足够的点击区域(最小 44x44px)

4.2.5 响应式设计

移动端适配建议:

  • 小屏幕下标签可以换行或使用水平滚动
  • 考虑将水平标签页切换为垂直布局
  • 调整标签内边距和字体大小

五、常见应用场景

5.1 产品详情页

<div
  role="tablist"
  aria-label="产品信息">
  <button
    role="tab"
    aria-selected="true"
    aria-controls="panel-overview">
    概览
  </button>
  <button
    role="tab"
    aria-selected="false"
    aria-controls="panel-features">
    功能
  </button>
  <button
    role="tab"
    aria-selected="false"
    aria-controls="panel-reviews">
    评价
  </button>
</div>

5.2 设置面板

<div
  role="tablist"
  aria-label="设置选项"
  aria-orientation="vertical">
  <button
    role="tab"
    aria-selected="true"
    aria-controls="panel-account">
    账户
  </button>
  <button
    role="tab"
    aria-selected="false"
    aria-controls="panel-privacy">
    隐私
  </button>
  <button
    role="tab"
    aria-selected="false"
    aria-controls="panel-notifications">
    通知
  </button>
</div>

5.3 代码示例展示

<div
  role="tablist"
  aria-label="代码示例">
  <button
    role="tab"
    aria-selected="true"
    aria-controls="panel-html">
    HTML
  </button>
  <button
    role="tab"
    aria-selected="false"
    aria-controls="panel-css">
    CSS
  </button>
  <button
    role="tab"
    aria-selected="false"
    aria-controls="panel-js">
    JavaScript
  </button>
</div>

六、最佳实践

6.1 选择合适的激活模式

  • 自动激活:面板内容已预加载,无明显延迟
  • 手动激活:面板内容需要异步加载,或加载时间较长

6.2 确保键盘可访问

  • 所有标签都必须可以通过键盘聚焦
  • 方向键在标签之间循环导航
  • Tab 键从标签列表移动到面板内容

6.3 提供清晰的视觉反馈

  • 激活的标签使用不同的样式(颜色、边框)
  • 焦点状态清晰可见
  • 未激活的面板完全隐藏

6.4 避免嵌套 Tabs

不要在 Tab Panel 内部嵌套另一个 Tabs,这会造成:

  • 键盘导航复杂且容易迷失
  • 屏幕阅读器用户难以理解层级关系
  • 视觉上的混乱

6.5 处理大量标签

如果标签数量过多:

  • 考虑使用垂直方向节省水平空间
  • 或者重新组织内容结构
  • 避免标签需要水平滚动

6.6 移动端适配

@media (max-width: 640px) {
  [role='tablist'] {
    flex-wrap: wrap;
  }

  [role='tab'] {
    flex: 1;
    min-width: 80px;
    padding: 10px;
    font-size: 14px;
  }
}

七、Tabs 与其他组件的选择

7.1 Tabs 与 Accordion 的选择

场景 Tabs Accordion
需要同时对比多个内容 ❌ 一次只能看一个 ✅ 可同时展开多个
水平空间有限 ❌ 需要水平排列标签 ✅ 垂直展开更省空间
内容有明确顺序 ✅ 标签顺序暗示优先级 ❌ 各面板相对独立
需要频繁切换内容 ✅ 点击标签即可切换 ❌ 需要展开/折叠操作
移动端优先 ❌ 水平空间受限 ✅ 垂直空间更充裕
键盘导航效率 ✅ 方向键快速循环 ⚠️ Tab 键逐个遍历
内容关联性 ✅ 同一主题不同方面 ✅ 相对独立的内容块
典型应用场景 产品详情页、设置面板 FAQ、内容列表、过滤器

选择建议:

  • 用 Tabs:内容关联紧密、空间充足、需要快速切换
  • 用 Accordion:需要对比多个内容、移动端、垂直空间充裕

7.2 Tabs 与 Menu 的选择

场景 Tabs Menu
页面内内容切换 ✅ 显示对应面板,不跳转 ❌ 预期会跳转页面
导航到不同页面 ❌ 不适合页面导航 ✅ 专为导航设计
执行操作(如下载) ❌ 不适用于操作 ✅ 可触发各种操作
内容关联性 ✅ 同一上下文相关内容 ❌ 通常相互独立
视觉反馈 ✅ 始终显示激活状态 ✅ 显示当前页面
键盘导航 ✅ 方向键循环,Tab 离开 ✅ 方向键导航,Enter 激活
ARIA 角色 tablist + tab + tabpanel menubar + menuitemnavigation + link
典型应用场景 产品详情、代码示例展示 主导航、用户操作菜单

选择建议:

  • 用 Tabs:同一页面内切换相关内容
  • 用 Menu:页面导航或执行操作

常见误区:

  • ❌ 使用 Tabs 作为主导航菜单(应使用 <nav> + <a>
  • ❌ 使用 Menu 展示同一页面内容(应使用 Tabs)
  • ❌ Tabs 标签使用 <a> 链接(应使用 <button>
  • ❌ 在移动端使用过多 Tabs(应考虑 Accordion)

八、总结

构建无障碍的 Tabs 组件需要关注:

  1. 正确的 ARIA 角色tablisttabtabpanel
  2. 完整的状态管理aria-selectedaria-controlstabindex
  3. 键盘导航支持:方向键循环、Home/End 快捷键
  4. 合适的激活模式:根据内容加载情况选择自动或手动激活
  5. 清晰的视觉反馈:激活状态、焦点状态明确可辨

遵循 W3C Tabs Pattern 规范,我们能够创建既美观又包容的标签页组件,为所有用户提供一致的体验。

文章同步于 an-Onion 的 Github。码字不易,欢迎点赞。

❌
❌