语义化表头必须用<thead>包裹<tr><th>,并设置scope属性明确关联范围,配合<caption>定义标题,避免display: block破坏表格结构。

用 <thead> 包裹 <tr><th> 才算真正语义化的表头
很多人以为只要写 <th> 就是表头,其实浏览器只认结构。没用 <thead> 包裹的 <th>,在屏幕阅读器、打印样式或 CSS 选择器(比如 thead th)里可能完全失效。
正确结构长这样:
<table>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>城市</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>28</td>
<td>北京</td>
</tr>
</tbody>
</table>
-
<thead>必须直接子元素是<tr>,不能跳级 - 同一行里的
<th>默认有加粗+居中,但样式可被 CSS 覆盖,语义不依赖外观 - 如果表头跨多行(比如“科目”下分“语文”“数学”),要用
rowspan和colspan配合<thead>,不能只靠视觉对齐
<th> 的 scope 属性决定它管哪一列/行
光有 <th> 不够,辅助技术需要知道这个表头“对应谁”。scope 就是干这个的:
-
scope="col":声明该<th>是上方整列的标题(最常用) -
scope="row":声明该<th>是右侧整行的标题(比如首列“张三”“李四”) -
scope="colgroup"或scope="rowgroup":用于带<colgroup>或多层表头的复杂表格
错误写法:<th>姓名</th> 没加 scope —— 屏幕阅读器可能读成“姓名,空白单元格”,无法关联数据行。
立即学习“前端免费学习笔记(深入)”;
用 <caption> 写表格标题,别塞在 <thead> 里
表格整体说明(比如“2024年Q1销售数据”)应该用 <caption>,它必须是 <table> 的第一个子元素:
<table> <caption>2024年Q1销售数据</caption> <thead>...</thead> <tbody>...</tbody> </table>
-
<caption>会被读屏软件优先朗读,比任何<th>都先识别 - 不要用
<h3>或普通<p>模拟标题——它不属于表格 DOM 结构,CSS 无法通过table caption精准控制 - 默认居顶,用
caption-side: bottom可以下移,但语义不变
CSS 里用 thead 固定表头滚动时容易漏掉 display: block 陷阱
想让表格内容区滚动、表头固定?常见做法是给 <tbody> 设 display: block; max-height: 300px; overflow-y: auto,但这时 <thead> 会脱离表格流,错位。
- 必须同时给
<thead>和<tbody>加display: table-header-group和display: table-row-group,否则列宽不一致 - 更稳妥的做法是避免用
display: block,改用position: sticky配合top: 0直接作用于<th>(需父<table>有border-collapse: collapse) - IE 不支持
sticky,如需兼容,得回退到 JS 控制 scrollTop + clone 表头,不是纯 CSS 能解决的
语义正确的表头,从来不只是为了好看,而是为了让代码能被机器准确理解。一旦漏掉 <thead> 或 scope,后续加筛选、导出 Excel、无障碍测试全都会卡在第一步。



















