rowspan属性必须写在起始行的<td>或<th>上,向下跨行占位,被跨行列必须彻底省略对应<td>标签,不可留空或写空标签;其值不能超过当前行至表格末尾的剩余行数,否则导致列错位或DOM结构异常。

rowspan 属性必须写在起始行的 <td> 或 <th> 上
跨行合并不是“哪一行加都行”,rowspan 只对它所在的那个单元格生效,并向下锁定对应列位置。比如你想让第二行第一列跨 3 行,就得把 rowspan="3" 写在第二行的 <td rowspan="3"> 里,而不是第一行或第四行。
常见错误现象:
- 写了
rowspan="3"却只看到 1 行高度——大概率写在了最后一行,没剩余行可跨 - 表格列错位、右侧内容整体右移——
rowspan所在行的其他<td>数量没同步减少
关键点:rowspan 值必须 ≤ 从当前行到表格末尾的剩余行数(含当前行)。它不改变当前行高度,只是“占位”:后续行同一列位置不能再出现 <td> 或 <th>。
被跨过的行必须彻底省略对应列的 <td> 标签
不是留空,不是写 <td></td>,是直接删掉那一列的整个 <td> 元素。浏览器靠 rowspan 的数值自动跳过指定行数,一旦多写一个 <td>,就会挤占空间、导致列偏移甚至 DOM 结构错乱(比如 tr.cells.length 拿不到预期值)。
立即学习“前端免费学习笔记(深入)”;
✅ 正确写法:
<tr> <td rowspan="3">张老师</td> <td>数学</td> </tr> <tr> <td>物理</td> <!-- 第一列省略 --> </tr> <tr> <td>化学</td> <!-- 第一列省略 --> </tr>
❌ 错误写法:
<tr> <td rowspan="3">张老师</td> <td>数学</td> </tr> <tr> <td></td> <!-- 空 td 会占位,破坏结构 --> <td>物理</td> </tr>
动态生成时容易漏掉的统计逻辑
服务端渲染或 JS 拼接表格时,rowspan 不是静态写死就能一劳永逸的——得先统计相同值连续出现的行数,再决定在哪一行写 rowspan,其余行跳过该列。
- 不能只看“值相等”,还要确认是否「相邻行」,中间隔了一行不同值,就得重置计数
- 通常只在重复块的第一行设置
rowspan,后面同组行对应列直接 omit(不生成<td>) - 用 JS 动态操作时,修改
rowspan属性后,DOM 会重排,但不会自动删除已被跨过的<td>,必须手动移除,否则显示重复 - Vue/React 中若用
v-for或map渲染,需提前聚合数据,而不是在模板里if-else判定——否则容易漏掉隐藏的<td>
rowspan 对样式和可访问性的影响
rowspan 本身不影响语义,但实际使用中常因配套缺失引发问题:
- 默认
border-collapse: separate会让合并单元格的边框“各自为政”,视觉上像断开或加粗;务必加table { border-collapse: collapse; },否则上下 border 会重复渲染 - 避免对
<td>设置vertical-align: bottom或top后又合并多行——文字可能贴顶或悬空,改用middle更稳 - 跨行的
<th>必须加scope="row"(横向标题)或scope="col"(纵向标题),否则读屏软件无法关联数据单元格 - 如果用了 CSS Grid 或 Flex 模拟表格,
rowspan完全无效,它只在原生 HTML 表格结构中起作用
最易被忽略的是:rowspan 单元格的 padding 仍作用于所有参与行,容易造成上下间距膨胀;而屏幕阅读器依赖行列关系理解结构,scope 缺失或表头缺失会导致“第几行第几列”逻辑错乱。



















