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

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











