必须先拆出 thead、tbody、tfoot,否则无法样式隔离或 JS 操作;隐式 tbody 不可选中,导致固定表头、滚动体、打印页脚等功能失效,且屏幕阅读器无法逻辑播报。

为什么必须先拆出 thead、tbody、tfoot
不加语义分层的表格,后续几乎没法做样式隔离或 JS 操作。比如你想给表体加滚动、固定表头、或单独给表尾加粗汇总行,<tr> 全混在一起时,CSS 选择器只能靠 nth-child 硬算,一加新列就全崩。浏览器解析时也默认把没包裹的 <code><tr> 全塞进隐式 <code>tbody,但这个隐式容器无法被 CSS 选中或 JS 获取 —— 你用 document.querySelector('tbody') 会返回 null。
拆分后带来的实际好处包括:
-
thead可配合position: sticky实现真·固定表头(不用 JS 模拟) -
tbody能独立设置 max-height + overflow-y: auto,滚动时不带表头/表尾 -
tfoot在打印时会自动出现在每页底部(前提是它在 HTML 中写在tbody后面) - 屏幕阅读器能按逻辑区块播报,而不是“第1行第1列…第1行第2列…”
colgroup 和 col 不是可选项,而是列级控制刚需
很多人直接对 th 或 td 写 width,结果发现表头列宽和数据列宽对不齐——因为 th 和 td 是内容驱动的,而 col 是结构驱动的。浏览器先按 col 分配列宽,再往里填内容。
典型错误写法:<th style="width: 120px">姓名</th>
<td style="width: 120px">张三</td>,一旦某行姓名超长,整列就撑开。
立即学习“前端免费学习笔记(深入)”;
正确做法是:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
<table>
<colgroup>
<col width="120">
<col width="80">
<col width="200">
</colgroup>
<thead><tr><th>姓名</th><th>年龄</th><th>备注</th></tr></thead>
<tbody><tr><td>张三</td><td>28</td><td>长期合作客户</td></tr></tbody>
</table>
注意:col 的数量必须和每行单元格数严格一致;width 值单位可以是 px、% 或无单位(表示相对比例);colgroup 必须紧贴 table 开始,不能放在 thead 里面。
合并单元格时,rowspan 和 colspan 的计算陷阱
合并不是“画个框”,而是告诉浏览器:“这个单元格要占用接下来 N 行/N 列的位置”,后续的 <tr> 必须主动跳过这些位置,否则渲染会错位。常见错误是只写 <code>rowspan="2",但第二行里还放了一个 <td>,导致多出一列。
<p>一个安全写法示例(跨两行的左侧标题 + 右侧两行数据):</p>
<pre class="brush:php;toolbar:false;"><table>
<tr>
<td rowspan="2">总览</td>
<td>Q1</td>
</tr>
<tr>
<td>Q2</td>
</tr>
</table></pre>
<p>关键点:</p>
<ul>
<li>
<code>rowspan 的值是“总共占几行”,不是“向下跨几行”
<td> 或 <code><th>
<li>如果某行单元格总数变少,浏览器不会报错,但视觉上会出现列错位或空白列</li>
<li>避免嵌套合并(比如一个 <code>td 同时设 rowspan="2" 和 colspan="2"),可读性和维护性极差重构后如何验证结构是否干净
最简单的验证方式是打开浏览器开发者工具,右键表格 → “Edit as HTML”,然后看 DOM 结构是否满足三个条件:
- 所有
<tr> 都明确包裹在 <code>thead、tbody或tfoot内,没有裸露在外的<tr><li> <code>colgroup在table下第一层,且col数量与每行<th>/</th> <td> 数量一致 <li>没有 <code><td> 直接子元素出现在 <code><table> 下(这种结构虽然能渲染,但语义失效) <p>真正难的不是写对标签,而是改旧代码时保持数据逻辑不变。比如后台吐出的 JSON 是扁平数组,前端模板里用 <code>v-for或map渲染时,容易忽略thead和tbody的分层边界,导致生成的 HTML 缺少语义容器——这时候得在模板层补一层 wrapper,而不是硬塞<tbody> 标签进去。</tbody>


















