全局工具类和重置类不应套用BEM命名,如.u-text-center、.visually-hidden等纯功能类无Block上下文,硬加前缀破坏语义与复用性;.reset-list、.no-margin等布局重置规则同理,须保持全局可用且不隶属任何Block。

工具类和重置类不该套BEM
像 .u-text-center、.visually-hidden 这类纯功能型工具类,本身没有 Block 上下文,硬加前缀如 .card__u-text-center 反而破坏语义、增加冗余。它们的作用是跨组件通用的样式干预,不属于任何业务块。
同理,.reset-list、.no-margin 是布局层重置规则,意图是抹平默认行为,不是某个 Block 的组成部分。强行挂靠到某个 Block 下,既违背设计初衷,也导致后续无法在别处复用。
- 判断依据:这个类是否只在某一个 Block 内部有意义?如果不是,就不该带
__ - 常见错误:给 Ant Design 的
Button外层加ant-button__icon—— SDK 自己控制内部类名,外部强加 BEM 会违反封装契约 - 替代方案:保持工具类全局可用,用 CSS Modules 或
:global()(仅限必要场景)隔离作用域
全局主题类和微前端子应用不适用
.theme-dark 这类类名作用于整个页面或根节点,影响的是渲染上下文而非某个 UI 块,它不属于任何一个 Block 的语义范围。加 Block 前缀如 app__theme-dark 会误导开发者以为它是 app 组件的变体,实际它控制的是所有子组件的配色逻辑。
微前端中已封装好的第三方 UI 子应用(如独立加载的报表模块),其内部 DOM 和类名由 SDK 全权管理。你无法也不应通过 BEM 规范去“规范”它的内部结构 —— 那属于另一个团队/系统的边界。
立即学习“前端免费学习笔记(深入)”;
- 关键信号:类名是否通过
document.documentElement或body设置?是 → 不属于 Block - 风险点:试图用 BEM 约束第三方组件,会导致样式覆盖冲突、热更新异常、甚至 JS 初始化失败
- 实操建议:用 CSS 自定义属性(
--theme-color)传递主题,让子应用自己消费,而不是靠 class 名继承
Element 已具备独立复用能力时必须升为 Block
当某个“看起来像 Element”的 UI 单元,在 ≥2 个不同路由或父组件中高频出现(比如 status-badge 出现在用户列表、订单页、通知弹窗),它就不再是某个 Block 的附属,而是具备完整语义、样式边界和交互逻辑的独立单元。
此时继续写成 user-card__status 或 order-detail__status 是错的。它已经脱离了单一归属,强行绑定只会让样式耦合、修改扩散、复用困难。
- 典型反例:
.form__field__label—— label 若含图标、辅助文本、校验状态,就该拆出.labelBlock,而不是层层嵌套 - 判断标准:删掉父 Block,这个 UI 片段是否还能被理解、被使用、有独立样式声明?能 → 它就是 Block
- 升级路径:
user-card__avatar→ 提取为独立.avatarBlock;search-input__icon→ 提取为.icon-button或.search-icon
SCSS 中嵌套生成非法类名是隐性越界
SCSS 的 &__ 语法很便利,但容易写出 .card__content__title 这种三层结构 —— 浏览器不报错,但它违反 BEM 最基本的「Element 只能直属于 Block」原则。这种写法会让调试者无法定位归属,复用时极易冲突。
更隐蔽的问题是空格嵌套:.card { &__content { &__title {} } } 编译后变成 .card__content .card__content__title,这已不是 BEM,而是后代选择器,彻底破坏封装性。
- 安全写法只有单层:
.card { &__title {} &__body {} &--featured {} } - 禁止任何形式的
&__xxx { &__yyy {} }或&__item &__icon(中间有空格) - CI 流程中必须跑
stylelint --config .stylelintrc.js并启用selector-bem-pattern插件,否则这类错误几乎必然漏过


















