多级表头需严格对齐总列数:colspan和rowspan必须使每行单元格数等于<colgroup>定义的列数,否则浏览器自动补空单元格导致样式错乱;所有th/td须显式声明border-bottom和border-right;隐藏列应使用visibility: hidden而非display: none。

多级表头的 colspan 和 rowspan 必须对齐总列数
浏览器渲染表格时,会自动补全缺失单元格——只要某行 colspan 总和不等于你定义的总列数(比如 6 列),它就会悄悄塞一个空 <td> 进去,导致 border 断开、文字错位、样式塌陷。这不是 bug,是规范行为。
<ul>
<li>先用 <code><colgroup> 显式声明列数和边框:
<colgroup> <col style="border-right: 1px solid #ddd"> <col style="border-right: 1px solid #ddd"> <col style="border-right: 1px solid #ddd"> <col> </colgroup>这里定义了 4 列,那每一行所有
<th> 的 colspan 加起来必须严格等于 4
colspan,比如 <th colspan="4">销售汇总</th>
<th colspan="2">华东</th>,后面再补一个 <th>华北</th>,加起来还是 4<th></th>——它会被算作一列,直接破坏对齐border-collapse: collapse 不等于自动有线
只设 border-collapse: collapse 不够。它只是让相邻边框合并,但若某个单元格没定义 border-bottom 或 border-right,合并时这条线就“消失”了,看起来像断了一截。
-
<table>必须设border-collapse: collapse,且不能被后代样式覆盖(检查 computed styles) - 所有
<th>和<td>都要显式声明border-bottom和border-right,哪怕设为none:th, td { border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; } - 想突出顶层标题?给
<thead>最后一行加粗底边:thead tr:last-child th { border-bottom: 2px solid #333; }
rowspan 跨行时,下方同列必须留空
跨行标题(如左侧“部门”竖着占三行)本身不打断横向线,但极易引发结构错乱:如果次级标题行在第 2 行同一列又放了个 <th>,浏览器会把它当新单元格处理,整行列数就超了。
-
rowspan必须放在该组行的**第一行对应位置**,比如<th rowspan="3">部门</th>写在第 1 行第 1 列 - 第 2 行、第 3 行的第 1 列**不能有任何
<th>或<td>**,否则结构崩坏 - 需要“每行都有底边”?别指望
rowspan自动继承——得手动给每一行的<tr>加border-bottom,或用伪元素模拟
响应式下隐藏列会导致 colspan 失效
用 display: none 隐藏某列时,colspan 计算逻辑还在原列数上运行,但视觉宽度已变,结果就是分割线突然偏移、表头悬浮、对不齐。
立即学习“前端免费学习笔记(深入)”;
- 禁用
display: none隐藏<th>,改用:th.hidden, td.hidden { visibility: hidden; width: 0; padding: 0; border: none; } - 配合媒体查询控制
colgroup中对应<col>的宽度,保持列总数不变 - 真要删列?用 JavaScript 动态重写整个
<thead>,而不是 CSS 隐藏
colspan”或者“哪一列多塞了一个空 <th>”。建议每次写完立刻检查:打开 DevTools → Elements → 看每行 <tr> 下的子节点数是否一致,再对照 <colgroup> 数列数。差一个,线就断。



















