应根据表头实际描述范围选择:描述下方列用 scope="col",描述右侧行用 scope="row";左上角必须为 scope="col" 的 <th>;禁用 scope="col row" 多值及 <td> 替代;scope="rowgroup" 仅限 <tbody> 内首行且需 colspan。

scope="col" 和 scope="row" 怎么选
选错 scope 是表格语义失效的头号原因。不是“第一行就该用 scope="col"”,而是看这个 <th> 实际描述的是**下方数据列**(用 col),还是**右侧同行数据**(用 row)。
常见错误现象:屏幕阅读器读到某单元格时只报“120”,不报“销售额”或“1月”;WAVE 工具提示 “Missing table header associations”。
- 首行所有
<th>:几乎都该加scope="col",包括左上角那个(如<th scope="col">Performance Tier</th>) - 首列(从第二行起)每个
<th>:必须用scope="row",不能写成<td>或留空 - 绝对不要在同一个
<th>上写scope="col row"—— HTML 不支持多值,浏览器会忽略整个属性
为什么左上角不能留空或塞 <td>
左上角单元格(第1行第1列)不是“占位符”,它是第一个列标题,同时天然承担行标题组的统领角色。人为改成 <td> 或留空 <th></th>,等于主动切断语义链。
使用场景:性能对比表、合同用量统计、课程时间表等二维结构表格。
立即学习“前端免费学习笔记(深入)”;
- 留空
<th></th>:屏幕阅读器会读作“空白”,后续所有列标题关联失败 - 误用
<td>:辅助技术直接跳过,认为该单元格是普通数据,不再尝试向上/向左找表头 - 正确做法:保留
<th scope="col">Performance Tier</th>,它既是第一列标题,也作为整张表的“主维度标识”被现代辅助技术识别
scope="rowgroup" 什么时候能用
scope="rowgroup" 不是给任意行标题用的,它只对嵌套在 <tbody> 内部的 <th> 有效,且必须配合 <tbody> 的天然分组语义。
性能 / 兼容性影响:Chrome、Firefox、Edge 均能正确解析 DOM 结构,但 NVDA、JAWS 等主流屏幕阅读器目前不主动播报“进入新行组”,所以它主要提升的是 DOM 语义完整性,而非即时可访问反馈。
- ✅ 正确:在第二个
<tbody>的首行放<th scope="rowgroup" colspan="4">Q3 Sales</th> - ❌ 错误:放在
<thead>或<tfoot>里;或没包裹在<tbody>中 - ❌ 错误:用
role="rowgroup"替代 ——<tbody>本身已有该语义,加 role 反而可能干扰解析
容易被忽略的细节:caption 和 thead/tbody 必须配对
没有 <caption> 或缺失 <thead>/<tbody>,scope 属性效果会打折扣。辅助技术依赖这些容器锚定上下文。
比如仅写 <tr><th scope="col">Name</th></tr> 而不包进 <thead>,某些旧版 JAWS 版本可能无法稳定推断列范围。
-
<caption>是表格的唯一官方标题,比aria-label更可靠,且支持 CSS 选择器caption -
<thead>不只是样式分组,它告诉辅助技术“这些<th>是所有后续<tbody>行的列头” - 多个
<tbody>是合法且推荐的,尤其用于逻辑分组(如按季度、按区域),每个都能独立关联自己的scope="row"行标题



















