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

表格结构决定类名层级,不是所有 <th> 都该套 <code>table__header
直接给每个 <th> 加 <code>table__header 是常见误区。真正该命名的是语义上构成「一个完整数据表」的容器块,比如用户管理列表、订单明细汇总——user-table 或 order-summary 才是 Block。里面的 <thead>、<code><tbody>、<code><th>、<code><td> 是结构骨架,不自动继承 Block 名;只有当某列有独立交互或样式逻辑(如可排序的“状态”列),才需定义 <code>user-table__status 这样的 Element。
常见错误现象:
-
<th class="table__header">姓名</th>—— “table” 是泛称,无业务含义,无法复用也无法定位到具体表格 -
<td class="status">已发货</td>—— 缺少 Block 上下文,和product-table__status冲突时样式互相覆盖
正确做法是先确认 Block 边界:<table class="user-table">,再按直属子关系定义:
<ul><li><code><thead class="user-table__head">
<li><code><th class="user-table__column-name">用户名</th>
<td class="user-table__cell-name">张三</td>
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> 前,例如:
<pre class='brush:php;toolbar:false;'><td data-label="邮箱">zhangsan@example.com</td>
</pre>
<p>但这只是辅助读屏的临时手段,不能因此省略语义类名。因为:</p>
<ul>
<li>
<code>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,尤其在微前端或多团队共存场景。



















