跨行单元格需用属性选择器(如[rowspan])配合bem modifier精准控制样式,避免依赖dom位置;必须统一设置vertical-align、padding等基础样式,并通过modifier实现响应式隐藏与语义化区分。

跨行单元格不能靠 tr 或 td 默认样式控制
HTML 表格里,rowspan 会让一个 td 占据多行,但它本身仍是单个 DOM 节点,没有“跨行状态”的语义标记。浏览器不会给它自动加类,CSS 也无法用 :nth-child 或父级选择器精准定位——因为视觉上的“第2行第1列”在 DOM 中可能根本不存在(被上一行的 rowspan="2" 吞掉了)。
常见错误是试图写 .table__row:nth-child(2) .table__cell--dept 去控制第二行的部门列,结果失效;或给所有 td[rowspan] 统一加边框,却误伤了表头里的 colspan 单元格。
- 真正能稳定识别跨行单元格的,只有它自己带的属性:
rowspan值大于 1 - BEM 不反对用属性选择器,但必须和 Modifier 配合,避免语义断裂:比如
.table__cell--dept[rowspan]比单纯[rowspan]更可控 - 不要在 JS 里动态加
table__cell--rowspan-3这类类名——值不固定、难维护,也违背 Modifier 应表达“业务状态”而非“渲染参数”的原则
table__cell--dept 这类修饰符要覆盖跨行单元格的默认对齐与内边距
原生 td 在跨行后,垂直对齐(vertical-align)常显突兀,尤其当同行其他单元格内容高度不一时。BEM 元素类必须接管这些基础样式,否则跨行单元格会“飘”在行中间或底部。
示例问题:部门名跨 5 行,但文字只贴顶部,下方大片留白;而右侧数据列内容居中,视觉失衡。
- 统一设
.table__cell--dept { vertical-align: middle; },而不是依赖td { vertical-align: inherit; } - 跨行单元格往往需要更大内边距来平衡视觉重量:
.table__cell--dept { padding: 16px 12px; } - 若该列需背景色区分,直接写
.table__cell--dept { background-color: #f8f9fa; },别指望colgroup > col.col-dept生效(Firefox 不支持col的背景)
合并单元格后的响应式隐藏必须用 Modifier 控制,不能删 DOM
小屏下,跨行的部门列或指标组标题常需隐藏,但不能用 display: none 简单干掉——这会破坏表格结构,导致剩余单元格错位,甚至让 rowspan 计算失效(浏览器仍按原行数预留空间)。
正确做法是用 BEM Modifier 把“隐藏”变成一种可预测的状态,并配合视觉补偿。
- 定义
.table__cell--dept--hidden@sm,在媒体查询中设visibility: hidden;+position: absolute; left: -9999px;,保留占位但不可见 - 同时给同行其他单元格加
table__cell--data--shifted@sm,微调padding-left补偿被“隐去”的列宽 - 绝对禁止用 JS 删除含
rowspan的td节点——哪怕只删一个,整行渲染都可能崩
跨行表头与普通单元格共用同一套 BEM 类,靠属性选择器补足差异
复杂报表里,表头常有 colspan,数据行有 rowspan,但它们可能是同一业务列(如“Q1–Q4 销售额”这个分组标题跨列,下面每季度数据又各自跨行)。如果拆成 table__header-cell--quarter 和 table__cell--quarter,样式维护就裂开了。
更合理的是共用 table__cell--quarter,再用 HTML 属性区分上下文:
<th class="table__cell table__cell--quarter" colspan="4">2024 销售额</th><td class="table__cell table__cell--quarter" rowspan="3">华东区</td>- CSS 中用
.table__cell--quarter[role="columnheader"]控制表头字体加粗,.table__cell--quarter[role="gridcell"]控制数据行文字颜色 - 若需兼容旧版 IE,改用
[data-role="header"]替代role属性,避免 aria 语义冲突
跨行样式真正的难点不在怎么写,而在怎么让不同角色(表头/数据/汇总)的单元格,在共享同一语义类的前提下,还能保持各自的行为边界——Modifier 是声明“是什么”,属性才是说明“此刻在扮演什么”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











