先记住这个答案
表格中的 <th> 不只是把文字加粗,它告诉浏览器和辅助技术这格是表头。简单表格里,列名写 <th scope="col">,每行的名称写 <th scope="row">,数据格就能与行列上下文联系起来。scope 是关联方向,而不是控制视觉样式;复杂表格如果一个数据格对应多层表头,再考虑 id 与 headers 明确列出所有表头。
<th>提供表头语义scope="col"对应列scope="row"对应行- 复杂跨层表头可用
headers精确关联
商品价格表要能知道哪一格是什么
只读出“39 元”,用户不知道是哪个商品、哪个字段。加上列头“价格”和行头“茶杯”,这格才有明确含义。
<table>
<caption>商品报价</caption>
<thead><tr><th scope="col">商品</th><th scope="col">价格</th></tr></thead>
<tbody>
<tr><th scope="row">茶杯</th><td>39 元</td></tr>
<tr><th scope="row">水壶</th><td>129 元</td></tr>
</tbody>
</table>阅读茶杯这一行的价格时,数据格能关联“茶杯”和“价格”。<caption> 说明整张表是什么,<th> 与 scope 说明内部各格的关系,职责不同。
鼠标用户可以靠横竖位置看出 39 元对应茶杯;读屏用户逐格移动时,原来的视觉位置不会自然变成语音上下文。这里把商品名写成行头,能让数据格在脱离整张表的视觉网格后仍有含义。若表格第一行只是装饰性标题,不应为了加粗而把它误写成列头。
表头也可以不用浏览器默认的粗体样式,CSS 怎么画不改变语义。别为了视觉效果把普通 <td> 写成 <th>,那会误导辅助技术。
复杂层级别硬套单层规则
有些报表把“第一季度”横跨一月、二月、三月,再在下面细分“收入”和“成本”。这时一个数据格可能需要关联多个表头,单个行列方向未必足够明确。
先尝试简化表结构;如果确实需要复杂多层表头,就给表头唯一 id,在对应数据格的 headers 属性里列出关联 ID。结构越复杂,越要用读屏实际走一遍。
scope="col" 适合列头管辖同一列的数据,scope="row" 适合每一行的行名。若一组数据被跨列的表头统管,还可按表结构考虑 colgroup 或 rowgroup,但前提是分组关系在标记中确实存在。给所有 <th> 一律写 scope="col" 看似省事,行名仍会被错误地解释为列头。
表格的视觉样式也要配合语义检查:响应式页面把列隐藏后,读屏关联仍按当前 DOM 表格结构工作。不要只在桌面宽度看一次,移动端若把表格改成卡片,也要确认每个数值旁仍有可理解的名称。
容易答错的地方
- 只用加粗样式做表头
- 视觉加粗不会给数据格建立表头语义,应使用
<th>。 - 把
scope当成 CSS 位置 - 它描述关联方向,不负责排版、宽度或固定表头。
面试官还会怎么问?
行头写在 <td> 里可以吗?
可以显示,但会失去明确的行表头语义;适合表头的格子应写 <th scope="row">。
什么时候用 headers?
一个数据格需要关联多个跨行跨列表头,scope 难以准确描述时使用。
<caption> 和列头是一回事吗?
不是。<caption> 给整张表命名,列头解释每列的数据含义。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。