Skip to content

表格可访问性

基于 HTML Living Standard · 核于 2026-06

速查

  • <caption> 是表的可访问名称:一句话讲清主题,读屏用户据此决定细读还是跳过
  • 表头一律用 <th> 并写 scopecol / row)——读屏滚到任意格都能播报它对应的行/列表头
  • 读屏有专门的「表格导航模式」:按行列方向移动焦点,每进一格自动念出关联的表头
  • 复杂表(多级表头 / 大量合并)必须用 headers/id 显式绑定,scope 推断会失准
  • <th>abbr 给冗长表头一个简短播报名;表若「在说明一个观点」,再配简短摘要降低认知负担
  • 长摘要用 aria-describedby 关联,或把表放进 <figure> + <figcaption>
  • 改了 CSS display 就要补 rolerole="table" / rowgroup / row / columnheader / rowheader / cell,否则无障碍树被打散
  • 交互表(可选中/二维键盘导航/可拖拽)该用 role="grid";行可展开折叠用 role="treegrid"
  • 第一性原则:表越简单越无障碍——少合并、少嵌套,胜过事后堆一堆 ARIA 补救

读屏用户是怎么「看」表的

视觉用户一眼就能把握表的行列结构,读屏用户却是线性听的——所以辅助技术专门为表格提供了「表格导航模式」:用户可以按上下左右在单元格间移动焦点,每进入一格,读屏会自动播报这格对应的行表头与列表头,再念格子内容。

这套机制能不能用,全看 HTML 写得对不对。它依赖三样东西:一个说明主题的 <caption>、用 <th> 标出的表头、以及把表头和数据格绑起来的 scope(或复杂表的 headers/id)。这三样齐了,读屏用户才能像看见网格的人一样在表里穿行;缺了,表对他们就是一串失去坐标的散数据。

第一支柱:<caption> 给表一个名字

html
<table>
  <caption>2021 年俱乐部成员状态</caption>

</table>

<caption> 是表的可访问名称。它对低视力用户和读屏用户尤其重要:先用一句话讲清「这是什么表」,他们就能快速判断这张表与自己是否相关,从而决定细读还是跳过——而不必让屏幕阅读器把一格格内容念完才搞懂主题。

除了 <caption>,也可以用 aria-labelaria-labelledby<table> 起名,但 <caption>默认且对所有人可见的语义元素,应优先使用。

第二支柱:<th> + scope 建立行列关联

把表头写成 <th> 并标注 scope,是表格无障碍的核心动作:

html
<tr>
  <th scope="col">姓名</th>
  <th scope="col">毕业年份</th>
</tr>
<tr>
  <th scope="row">娄敏秋</th>
  <td>1956</td>
</tr>

这样「1956」这格就拥有两个表头——「毕业年份」(列)与「娄敏秋」(行)——读屏会告诉用户「这是娄敏秋的毕业年份」。即便表很长、表头早滚出屏幕,这层关联依然牢固。scopecol / row 覆盖绝大多数规整表;rowgroup / colgroup 用于「一个表头统领整段行/整组列」(详见 单元格与表头关联)。

第三支柱:复杂表用 headers/id

规范明确指出:结构复杂的表——表头或单元格被合并、或有两级以上行/列表头——需要显式标明关联的表头格。这种表 scope 的自动推断会失准,必须给每个 <th>id,再在数据格上用 headers 列出它隶属的所有表头 id:

html
<td headers="class-a final">92</td>

读屏会据此播报「一班 / 期末 / 92」。这是无障碍领域对「拆不开的复杂表」的终极手段(完整示例见 单元格与表头关联)。

降低认知负担:摘要、abbr<figure>

不是所有用户都有相同的认知能力。规范提醒:当一张表**「在说明某个观点」或需要解读**时,应额外给一段简短摘要,帮读者快速抓住要点:

  • 长摘要:用 aria-describedby 把表关联到页面上一段描述文字;或把表放进 <figure>,用 <figcaption> 写说明。
  • 冗长表头:用 <th abbr="简称"> 给读屏一个简短播报名,避免每念一格数据都重复一长串表头全称。
html
<figure>
  <figcaption>各季度营收同比增长(数据来源:财报)。Q3 受促销拉动明显。</figcaption>
  <table>…</table>
</figure>

改了 display,务必补回 role

这是响应式表格最隐蔽的陷阱。如果你用 CSS 改了表格元素的 display(例如把 <table> 改成 display: block、把行改成 display: flex 来做手机端堆叠布局),表格的隐式 ARIA 语义会被破坏——浏览器不再把它当成 table / row / cell,无障碍树被打散,前面三支柱全部失效。

web.dev 给出的对策是:一旦为表格元素改了 display,就显式补回对应的 role,即便看起来冗余:

元素需补的 role
<table>role="table"
<thead> / <tbody> / <tfoot>role="rowgroup"
<tr>role="row"
<th>(列)role="columnheader"
<th>(行)role="rowheader"
<td>role="cell"

「看起来多余」不等于可以省

display 属性会实打实地影响无障碍树。改了 display 又不补 role,视觉上表格照常,读屏却已读不出行列关系——这是典型的「看不见的回归」。响应式方案务必连带验证无障碍。

交互表:role="grid"role="treegrid"

普通展示型数据表用原生 <table> 即可。但当表格带交互时,要换更强的角色:

  • role="grid":表格维护选中状态、支持二维(行列双向)键盘导航、或允许重排单元格时使用;
  • role="treegrid":在 grid 基础上,行还能展开 / 折叠(树形表格)时使用。

这两种角色伴随一整套键盘交互契约(方向键移动、Enter/Space 操作等),用它们就得把交互补全,否则反而更糟。普通只读表不要乱加 grid

第一性原则:简单 > 补救

贯穿本页的一条主线:表越简单,越无障碍。少合并、少嵌套、少两级表头的表,哪怕不加 scope / headers 也更容易被理解,维护成本也更低。ARIA(roleheaders/idaria-describedby)是「原生结构表达不了时」的补救,不是用来给一张过度复杂的表打补丁。先把表设计简单,再谈无障碍增强。

小结

表格无障碍立在三根支柱上——<caption> 给名字、<th> + scope 建关联、复杂表用 headers/id 显式绑定;改 display 必补 role,交互表才用 grid / treegrid,而一切的前提是把表设计得足够简单。下一页把视角拉到最根本的反模式:为什么绝不能拿表格来排版,以及响应式表格该怎么做:数据表 vs 布局表