BEM命名必须遵循block__element--modifier顺序,因块是独立组件、元素属块内部、修饰符仅描述状态变体;顺序错乱会导致语义断裂、复用失效、样式覆盖混乱及维护成本飙升。

为什么block__element--modifier不能写成block--modifier__element
顺序错乱会导致语义断裂和复用失效。BEM强制约定层级:块(block)是独立组件单元,元素(element)属于块的内部结构,修饰符(modifier)只描述块或元素的**状态变体**,不改变归属关系。
-
button__icon--large合理:表示 button 块下的 icon 元素处于 large 状态 -
button--large__icon错误:large 本应修饰整个 button,却强行绑定到 icon,导致无法单独控制 button 尺寸而不影响 icon - 浏览器渲染时无报错,但 CSS 选择器权重、覆盖逻辑、维护成本全乱套
如何让--disabled修饰符真正“接管”所有子元素样式
修饰符不是装饰贴纸,它得能穿透到底层元素。常见写法.button--disabled .button__text看似可行,但耦合过重,且无法响应子元素自身状态变化(比如 input 内部的 :focus)。
- 正确做法:在 block 层统一加
aria-disabled="true",再用属性选择器驱动样式:.button[aria-disabled="true"] .button__text - 避免用
.button--disabled .button__icon这类后代选择器,改用.button--disabled .button__icon, .button__icon.button--disabled双路径覆盖(后者用于 icon 自身也可被独立禁用) - 注意:若元素本身支持原生 disabled(如
),优先用 HTML 属性而非 class,CSS 用button:disabled更可靠
当__list-item需要横向排列又需要悬停高亮,修饰符怎么拆
一个修饰符不该承担多个职责。横向排列是布局行为,悬停是交互反馈,混在一个 class 里(如 --horizontal-hover)会让组合爆炸、难以测试。
- 拆成两个独立修饰符:
list--horizontal控制flex-direction和间距,list-item--hoverable控制:hover样式 - 关键点:修饰符之间必须正交——
list--horizontal list-item--hoverable能自由组合,不影响彼此逻辑 - 别在
list--horizontal里写&__item:hover,那等于把交互逻辑硬编码进布局修饰符,后续想关掉 hover 只能加!important或重写整条规则
用 PostCSS 插件自动校验 BEM 命名是否合规
人工检查易漏,尤其在多人协作或老项目增量改造时。postcss-bem-linter 可在构建阶段报错,但默认配置太松,需调严。
- 启用
preset: 'bem'并开启strict: true,否则block__elem--mod--another这种非法双修饰符不会报警 - 排除动态生成类名场景:在
ignore: [/.+dynamic.+/]中明确列出 JS 拼接的 class,避免误报 - 最常被忽略的是伪类与修饰符混用,如
.button--primary:hover—— 这违反 BEM 原则,应改为.button--primary.button--hovered并由 JS 切换
BEM 的修饰符层不是样式补丁,它是组件状态的声明式映射。一旦开始用 JS 直接操作 className 拼接字符串,或者在 CSS 里写 &__item:hover 这种嵌套,就等于把样式逻辑悄悄塞回了实现细节里。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











