caption必须作为table的首个子元素,否则丧失语义;thead、tbody、tfoot为结构刚需,不可省略;th用于表头且需配合scope或headers明确归属,禁用td冒充表头。

必须把 caption 放在 table 的第一个子位置
很多开发者写完 thead 才想起加标题,随手把 caption 插在 thead 后面——这会让它失去语义,屏幕阅读器直接跳过,搜索引擎也不识别。HTML 规范强制要求 caption 是 table 的**首个子元素**。
常见错误现象:<table><thead>...</thead><caption>销售数据</caption></table> —— 浏览器会把它当普通文本渲染,不是标题。
- ✅ 正确顺序:
<table><caption>2026年Q3用户活跃度统计</caption><thead>...</thead><tbody>...</tbody></table> - 标题文案别写“表格一”“数据表”,要带时间、对象、维度,比如
2026年8月各渠道转化率(UV→订单) - 不要用
<p class="table-title">替代caption,CSS 隐藏或浮动后,辅助技术基本不可读
thead、tbody、tfoot 不是可选装饰,而是结构刚需
没加 thead 和 tbody 的表格,对人眼可能看起来一样,但对屏幕阅读器、打印样式、JS 操作(比如 document.querySelector('tbody tr'))和 CSS 选择器(如 tbody tr:nth-child(odd))都会出问题。
使用场景:哪怕只有一行表头 + 两行数据,也应显式包裹。复杂表格中,tfoot 放汇总行时,即使写在 HTML 中间(tbody 前),浏览器也会自动渲染到底部,且支持打印分页重复显示。
立即学习“前端免费学习笔记(深入)”;
-
thead必须包含至少一个tr,里面建议全用th;不要混用td -
tbody可以有多个,适合逻辑分组(如按地区、按月份拆成不同tbody) -
tfoot要放在tbody之后,但不能放在thead前——顺序错会导致 DOM 解析异常
别滥用 rowspan 和 colspan,优先用 scope 或 headers 明确单元格归属
合并单元格本身不破坏语义,但一旦合并后,屏幕阅读器无法自动判断某数据单元格对应哪个表头。比如一个跨三列的“总计”单元格,不加说明,用户听到的只是“12456”,不知道这是哪几列的总和。
解决方法不是靠视觉对齐,而是靠属性绑定:
- 简单行列关系:给
th加scope="col"(列标题)或scope="row"(行标题) - 复杂嵌套表头(比如“Q1销售额”下分“线上”“线下”):不用
scope,改用id+headers属性,例如<th id="q1-online">Q1 线上</th>对应的<td headers="q1-online">24300</td> - 避免
rowspan="10"这类大跨度合并——可读性差,JS 动态操作易出错,也增加无障碍测试失败风险
th 和 td 不能互换,尤其注意表头行里混用 td
看到有人写 <tr><td>姓名</td><td>年龄</td></tr> 当表头用,这是典型语义缺失。虽然浏览器照样加粗居中(取决于 UA 样式),但辅助技术完全无法识别这是标题,搜索爬虫也不会赋予关键词权重。
th 的核心作用不是“看起来像标题”,而是“告诉机器这是标题”。它的默认样式只是副作用。
- 所有列标题、行标题都必须用
th,哪怕它在tbody里(比如首列为“产品A”的行标题) - 如果某列需要左对齐或不加粗,用 CSS 覆盖,而不是换成
td - 不要为了省事,在
thead外单独写一行tr来放标题——必须包进thead才算语义完整
真正难的不是记住标签名,而是每次写表格时下意识问一句:“如果关掉 CSS,去掉鼠标,只靠键盘和语音,这个表格还能被准确理解吗?”——答案藏在 caption 的位置、th 的存在、scope 的设置里,不在边框粗细或颜色深浅中。



















