BEM 命名应以业务语义而非 DOM 结构为锚点,table 不作 Block,须按功能拆分为 user-list-table 等独立 Block;列修饰符如 --status 表达职责,状态交由行修饰符(如 --pending)承载;样式优先用属性选择器增强语义,响应式通过 display: none 隐藏列,修饰符语义须跨表格一致。

表格的 BEM 命名不是给 tr 和 td 贴标签,而是用业务语义锚定结构——user-list-table__row 不代表“所有行”,只代表“用户列表中的一行”;列不存在独立 DOM,必须靠 user-list-table__cell--status 这类修饰符表达职责。
为什么不能把 table 当作 Block 直接套用
原生 table 标签自带隐式语义和默认样式(如 border-collapse、vertical-align),强行统一前缀如 table__row 会导致:浏览器对 tr 的样式限制无法绕过;框架(React/Vue)动态渲染时,colgroup 易错位;调试时搜 table__ 会命中大量无关组件,失去语义隔离。
正确做法是按功能切块:user-list-table、order-summary-table、audit-log-table。每个 Block 独立维护,互不污染。
__cell--xxx 修饰符怎么设计才真正管用
修饰符必须反映列的业务角色,而非视觉或位置。比如“状态列”在多个表格中都存在,就统一用 --status,而不是 --col3 或 --blue-bg。
-
user-list-table__cell--status→ 控制文字居中、状态图标、背景色 -
user-list-table__cell--date→ 控制日期格式缩写、时区提示 tooltip -
user-list-table__cell--actions→ 控制按钮间距、悬停展开逻辑
避免写 user-list-table__cell--pending 这类状态修饰符直接挂在单元格上——它应该属于数据状态,由 JS 动态加在 user-list-table__row--pending 上,保持列修饰符专注“职责”,行修饰符专注“状态”。
表头和单元格样式不一致?别硬写 th 和 td 分开规则
用属性选择器补足语义比依赖标签更可靠。比如排序功能:
th[data-sortable].user-list-table__header--name::after 控制箭头图标,不影响其他 user-list-table__header--name;td.user-list-table__cell--name[data-editable] 触发可编辑态,不耦合 contenteditable 属性到类名里。
注意:IE11 不支持 [data-status="active pending"] 这种空格分隔多值写法,需改用 [data-status~="active"] 才能匹配含 active 的任意空格分隔值。
响应式隐藏某列时,别动 HTML 结构
隐藏列不是删 DOM,而是控制显示。用媒体查询配合修饰符即可:
@media (max-width: 768px) { .user-list-table__cell--phone { display: none; } }
这样既保持 DOM 稳定(利于 SSR 和焦点管理),又避免 JS 操作 colgroup 导致的渲染错位。若需保留语义但视觉隐藏,可用 visibility: hidden + position: absolute 配合 clip-path,但绝大多数场景 display: none 更直接可靠。
最易被忽略的是:修饰符命名一旦定下,就要贯穿整个表格生命周期——--status 在用户列表里是“启用/禁用”,在订单表里就不能突然变成“已发货/已取消”,否则 CSS 复用就失效了。语义一致性比视觉效果更难维持,也更重要。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











