rowspan必须写在起始行的td或th上,向下跨行占位,被跨行对应列的td必须完全省略而非留空;值不能超过剩余行数,否则导致列错位或DOM结构异常。

rowspan 属性必须写在起始行的 td 或 th 上
跨行合并不是“在哪一行加都行”,rowspan 只对它所在的那个单元格生效,并向下锁定对应列位置。比如想让第一列从第 2 行开始跨 3 行,就得把 rowspan="3" 写在第 2 行的 <td rowspan="3">内容</td> 里,而不是第 1 行或第 4 行。
常见错误现象:
- 写了
rowspan="3"但只看到 1 行高度——很可能写在了最后一行,没剩余行可跨 - 表格列错位、右侧内容整体右移——
rowspan所在行的其他td数量没同步减少
关键点:
-
rowspan值必须 ≤ 从当前行到表格末尾的剩余行数(含当前行) - 它不改变当前行高度,只是“占位”:后续行同一列位置不能再出现
td或th - 如果该列本该有内容(比如“部门 A”),只在首行写
<th rowspan="4">部门 A</th>,后面 3 行这个位置必须完全不写标签
被跨过的行必须彻底省略对应列的 td 标签
不是留空,不是写 <td></td>,是直接删掉那一列的整个 td 元素。浏览器靠 rowspan 的数值自动跳过指定行数,一旦多写一个 td,就会挤占空间、导致列偏移甚至 DOM 结构错乱(row.cells.length 拿不到预期值)。
示例对比:
<tr> <td rowspan="3">张老师</td> <td>数学</td> </tr> <tr> <td>物理</td> <!-- ✅ 正确:第 1 列省略 --> </tr> <tr> <td>化学</td> <!-- ✅ 正确:第 1 列省略 --> </tr>
错误写法:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
<tr> <td rowspan="3">张老师</td> <td>数学</td> </tr> <tr> <td></td> <!-- ❌ 错误:写了空 td,会占位 --> <td>物理</td> </tr>
colspan 和 rowspan 同时用时,列数要动态重算
一个单元格同时设 rowspan="2" 和 colspan="3",就覆盖了 2 行 × 3 列共 6 个原始格子。这意味着:当前行剩下可用列数 = 总列数 − 3;下一行该列位置不能出现任何 td,且该行其余 td 的 colspan 总和也得补足剩余列数。
容易踩的坑:
- 当前行写了
<td colspan="3">标题</td>,又跟了一个普通<td>A</td>,结果整行变成 4 列宽,表格自动换行或撑开 - 下一行仍按“总列数”生成全部
td,没减去被上层rowspan占用的列,导致row.cells[0]是undefined - 打印 PDF 或屏幕阅读器解析失败——结构错乱比样式错乱更难调试
建议做法:手绘表格矩阵草图,标出每个单元格覆盖的行列范围,再转成 HTML;复杂表头别靠试错硬调。
动态生成表格时,rowspan 逻辑必须前置聚合
服务端渲染或 JS 拼接时,不能边遍历边决定要不要写 rowspan。必须先扫描数据,统计相同值连续出现的行数(注意:必须是相邻行,中间断开就得重置计数),然后只在每组首行写 rowspan,其余行跳过该列。
Vue/React 中尤其明显:
- 在
v-for或.map()模板里用v-if隐藏td不够——DOM 还在,只是不可见,仍参与布局 - 正确做法是提前把原始数据按分组聚合,生成带
rowspan字段的扁平数组,模板里只做纯渲染 - JS 动态修改
rowspan属性后,不会自动删掉已被跨过的td,得手动remove(),否则显示重复
border-collapse 和 vertical-align 这类样式问题,反而容易修;真正难调的是结构层面的列数错配——它不报错,但导出、读屏、JS 计算全崩。

















