BEM 命名应以业务语义 Block(如 user-table)为根,th/td 等结构元素需按直属关系命名,colspan/rowspan 单元格须单独定义 Element,工具类须用 u- 前缀隔离,data-label 不能替代语义类名。

表格结构决定类名层级,不是所有 都该套 table__header直接给每个 加 table__header 是常见误区。真正该命名的是语义上构成「一个完整数据表」的容器块,比如用户管理列表、订单明细汇总——user-table 或 order-summary 才是 Block。里面的 、、、 是结构骨架,不自动继承 Block 名;只有当某列有独立交互或样式逻辑(如可排序的“状态”列),才需定义 user-table__status 这样的 Element。常见错误现象:
-
姓名 —— “table” 是泛称,无业务含义,无法复用也无法定位到具体表格
-
已发货 —— 缺少 Block 上下文,和 product-table__status 冲突时样式互相覆盖
正确做法是先确认 Block 边界:,再按直属子关系定义:
用户名
张三
colspan 和 rowspan 单元格需要单独的 Element 类名
带 colspan 或 rowspan 的单元格在视觉和语义上都脱离了常规行列结构,不能复用 user-table__cell-xxx。它往往承担分组标题、汇总说明等角色,必须显式命名以支持样式隔离和 JS 操作。
例如合并三列的“操作”栏:
<tr>
<td colspan="3" class="user-table__actions-header">批量操作</td>
</tr>
而不是:
<td colspan="3">批量操作</td>
原因:
-
user-table__actions-header 明确表达“这是本表的操作区头部”,后续加 hover 效果或 JS 绑定事件时可精准选择
- 若只靠
colspan 属性筛选,CSS 中写 td[colspan="3"] 兼容性差,且无法区分“操作头”和“数据汇总行”
- 屏幕阅读器不会自动识别
colspan 的语义意图,必须靠类名 + ARIA 补充(如 aria-role="columnheader")
工具类必须加 u- 前缀,且不能混入 BEM Block
像隔行变色、文字截断、固定列宽这类纯表现行为,绝不能塞进 user-table__cell 的 Modifier 里(如 user-table__cell--striped)。它们与业务逻辑无关,也不随 Block 变化,强行绑定只会让样式层越来越重。
应该统一用工具类前缀隔离:
-
u-bg-striped(替代 CSS 中的 tr:nth-child(even))
-
u-text-ellipsis(单行截断)
-
u-w-120(固定宽度,数值单位明确)
使用时直接叠加:
<td class="user-table__cell-name u-text-ellipsis">这个用户名超长了会自动截断</td>
关键点:
- 工具类不参与 BEM 层级推导,
u- 是硬性隔离边界
- 禁止出现
user-table__cell u-text-ellipsis 以外的组合,比如 user-table__cell--ellipsis 就是错的
- 所有
u- 类必须在全局 CSS 中定义,不能按表格局部覆盖
响应式表格中,data-label 属性不替代语义类名
移动端折叠表格常用 data-label 把列名注入 前,例如:<td data-label="邮箱">zhangsan@example.com</td>
但这只是辅助读屏的临时手段,不能因此省略语义类名。因为:
-
data-label 不参与 CSS 选择,无法做列级样式控制(如“邮箱列右对齐”)
- JS 查找特定列内容时,仍需靠类名定位:
document.querySelectorAll('.user-table__cell-email') 比遍历 data-label 稳定得多
-
data-label 值是字符串,大小写/空格/翻译易出错;类名是静态标识,更可靠
所以正确写法是两者并存:
<td class="user-table__cell-email" data-label="邮箱">zhangsan@example.com</td>
注意:data-label 必须加项目前缀避免冲突,比如 data-user-label,尤其在微前端或多团队共存场景。
table__header直接给每个 常见错误现象: 正确做法是先确认 Block 边界: 带 例如合并三列的“操作”栏: 而不是: 原因: 像隔行变色、文字截断、固定列宽这类纯表现行为,绝不能塞进 应该统一用工具类前缀隔离: 使用时直接叠加: 关键点: 移动端折叠表格常用 但这只是辅助读屏的临时手段,不能因此省略语义类名。因为: 所以正确写法是两者并存: 注意: 加 table__header 是常见误区。真正该命名的是语义上构成「一个完整数据表」的容器块,比如用户管理列表、订单明细汇总——user-table 或 order-summary 才是 Block。里面的 、
、
、 是结构骨架,不自动继承 Block 名;只有当某列有独立交互或样式逻辑(如可排序的“状态”列),才需定义 user-table__status 这样的 Element。
—— “table” 是泛称,无业务含义,无法复用也无法定位到具体表格姓名 —— 缺少 Block 上下文,和 已发货 product-table__status 冲突时样式互相覆盖,再按直属子关系定义:
用户名 张三
colspan 和 rowspan 单元格需要单独的 Element 类名colspan 或 rowspan 的单元格在视觉和语义上都脱离了常规行列结构,不能复用 user-table__cell-xxx。它往往承担分组标题、汇总说明等角色,必须显式命名以支持样式隔离和 JS 操作。<tr>
<td colspan="3" class="user-table__actions-header">批量操作</td>
</tr>
<td colspan="3">批量操作</td>
user-table__actions-header 明确表达“这是本表的操作区头部”,后续加 hover 效果或 JS 绑定事件时可精准选择colspan 属性筛选,CSS 中写 td[colspan="3"] 兼容性差,且无法区分“操作头”和“数据汇总行”colspan 的语义意图,必须靠类名 + ARIA 补充(如 aria-role="columnheader")工具类必须加
u- 前缀,且不能混入 BEM Blockuser-table__cell 的 Modifier 里(如 user-table__cell--striped)。它们与业务逻辑无关,也不随 Block 变化,强行绑定只会让样式层越来越重。
u-bg-striped(替代 CSS 中的 tr:nth-child(even))u-text-ellipsis(单行截断)u-w-120(固定宽度,数值单位明确)<td class="user-table__cell-name u-text-ellipsis">这个用户名超长了会自动截断</td>
u- 是硬性隔离边界user-table__cell u-text-ellipsis 以外的组合,比如 user-table__cell--ellipsis 就是错的u- 类必须在全局 CSS 中定义,不能按表格局部覆盖响应式表格中,
data-label 属性不替代语义类名data-label 把列名注入 前,例如: <td data-label="邮箱">zhangsan@example.com</td>
data-label 不参与 CSS 选择,无法做列级样式控制(如“邮箱列右对齐”)document.querySelectorAll('.user-table__cell-email') 比遍历 data-label 稳定得多data-label 值是字符串,大小写/空格/翻译易出错;类名是静态标识,更可靠<td class="user-table__cell-email" data-label="邮箱">zhangsan@example.com</td>
data-label 必须加项目前缀避免冲突,比如 data-user-label,尤其在微前端或多团队共存场景。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











