先记住这个答案
<caption> 写在 <table> 标签内部的第一行,渲染出来就是一段可见文字,视觉用户和屏幕阅读器都能拿到。aria-label 写在 <table> 标签上,页面上不显示任何内容,只有屏幕阅读器读到这张表格时才会报读。想让所有人都知道这张表是什么意思,用 <caption>;设计稿不允许出现可见标题时,再退而用 aria-label。
<caption>在页面上可见,语义和可访问性都有aria-label只面向辅助技术,页面上看不到- 优先用可见的
<caption> <caption>是表格的首个子元素
实际写法对比
在一个展示季度销售额的表格上,两种写法看起来差不多,但浏览器处理方式完全不同。
<caption> 写法和 aria-label 写法HTML<!-- 方式一:caption,页面上会显示"2024 年各季度销售额" -->
<table>
<caption>2024 年各季度销售额</caption>
<tr>
<th scope="col">季度</th>
<th scope="col">销售额</th>
</tr>
<tr>
<td>Q1</td>
<td>320 万</td>
</tr>
</table>
<!-- 方式二:aria-label,页面上看不到标题文字 -->
<table aria-label="2024 年各季度销售额">
<tr>
<th scope="col">季度</th>
<th scope="col">销售额</th>
</tr>
</table>第一种写法中,<caption> 会成为表格的可访问名称,同时页面上方也能看到标题。第二种写法同样能提供可访问名称,但页面上没有标题文字;具体怎样报读名称与行列数,取决于读屏器。
什么时候用哪个
大多数场景下优先选 <caption>,因为它同时服务两类用户。后台管理系统里一页摆了好几张表格,每张表上方有个 <caption> 写清楚"用户列表""订单记录",视觉用户一扫就知道哪张是哪张。
如果 UI 设计已经在表格上方放了一个 <h3> 标题,再加 <caption> 会多出来一行重复文字。这时可以用 aria-labelledby 指向那个 <h3> 的 id,这样既不重复又保留了语义。aria-label 一般是最后的选择,只在周围确实没有可指向的可见元素时使用。
aria-labelledby 指向外部标题HTML<h3 id="user-heading">活跃用户</h3>
<table aria-labelledby="user-heading">
<tr>
<th scope="col">姓名</th>
<th scope="col">最后登录</th>
</tr>
</table>这样屏幕阅读器进入表格时会读出"活跃用户",和可见的 <h3> 内容一致。
容易答错的地方
- 同时写
<caption>和aria-label - 如果两个都写,
aria-label会覆盖<caption>作为表格的可访问名称,但<caption>仍然是可见内容。视觉用户看到的标题与辅助技术读到的名称可能不一样,反而制造了混乱。选一个就好。 - 把
<caption>放在<table>中间 <caption>必须是<table>的第一个子元素。放在<tr>后面,浏览器虽然大概率还是能渲染出来,但 HTML 校验器会报错,辅助技术的行为也不可预测。
面试官还会怎么问?
<caption> 的样式怎么调?
<caption> 默认以表格标题盒显示,能用 CSS 设置字体、颜色、对齐。caption-side: bottom 可以把它挪到表格下方显示,但不影响 DOM 顺序;具体报读顺序仍应在目标读屏环境里确认。
如果 <caption> 的文字太长,有没有替代方案?
可以在 <caption> 里只写一句简短的标题,详细说明放在 <caption> 外面用普通段落写。或者用 aria-describedby 指向一段额外描述,让屏幕阅读器在报读完标题后再报读补充信息。
不加任何标题,屏幕阅读器会怎么处理表格?
屏幕阅读器会直接报读"表格,X 行 Y 列",然后跳到第一个单元格。用户只知道页面上有一张表,但不知道这张表是干什么的,如果页面上有多张表就很难区分。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。