BEM 文档必须明确 Block、Element、Modifier 的物理边界与使用契约:Block 名须与文件名、DOM 节点严格一致;Element 仅限直接子节点且不可嵌套;Modifier 须声明叠加规则与互斥警告,禁止视觉值直命名。

Block 名必须与文件名、DOM 节点严格一致
文档里只写「按钮用 button 作 Block」是无效的。开发者真正需要知道的是:button 必须对应一个可独立渲染的 DOM 节点,比如 <button class="button"> 或 <div class="button">,不能只是布局用的空 <div>。
文件名、组件名、Block 类名三者必须完全一致:Button.vue → button,不是 btn、ui-button 或 Button(大小写不一致会破坏构建工具识别)。
- 常见错误:文档写 “card 组件”,但实际文件叫
CardContainer.vue,导致 postcss-bem 报Unknown block "card" - 如果图标在按钮、导航、弹窗中都复用,它就得是独立 Block
icon,不能塞进button__icon—— 否则下游改一个地方,三处都得跟着调 - 泛义名如
form、article、section要加前缀或换名:login-form✅,.form❌;blog-post✅,.article❌
Element 必须标注 HTML 中的合法位置
__ 不表示 DOM 嵌套深度,但 Element 在 HTML 里的挂载位置有硬约束。文档不写清楚,开发者一写错层级,样式就失效,还查不出原因。
例如 button__text 只能是 button 的直接子节点,中间不能隔 <span> 或 <div>;card__title 也不能出现在 <div class="card__header"><h2 class="card__title"> 里——因为 card__header 不是 Block,只是个普通容器,card__title 实际已脱离 card 直接子级范围。
立即学习“前端免费学习笔记(深入)”;
- 禁止出现
button__text__icon:Element 不允许嵌套 Element,这是结构越界信号 - 设计稿里“带图标的按钮文字”不是嵌套问题,而是并列需求:应拆成
button__text+button__icon - SCSS 中避免
&__input { &__icon { } },编译后生成后代选择器,破坏 BEM 封装性
Modifier 文档必须声明叠加规则与冲突警告
修饰符不是贴纸,button--disabled 和 button--primary 能不能共存?user-card--small 和 user-card--featured 同时加会不会打架?这些必须白纸黑字写进文档,否则 CSS 规则靠权重硬扛,后期必崩。
关键判断标准是:Modifier 是否描述一种可预期、可测试的布尔状态。颜色、尺寸、位置这类视觉值不能直接进修饰符名 —— button--red ❌,应为 button--danger;user-card--small ❌,应为 user-card--compact 或交由媒体查询控制。
-
button--large和button--small互斥,文档需加 ⚠️:“二者不可同时使用,否则尺寸定义冲突” -
card__title--large合法,但card--featured__title--large是非法结构 —— 修饰符只能作用于 Block 或直属 Element,不能降级穿透 - 所有修饰符类必须作为额外 class 显式添加到对应 DOM 节点上,不能靠 JS 动态拼字符串生成(如
el.className = 'button ' + type + '--' + state)
文档本质是模块契约说明书,不是类名列表
BEM 文档失效的典型场景,不是语法写错,而是契约没说清:某个 Element 是否允许嵌套?Modifier 叠加后 CSS 是否仍生效?Block 的物理边界是否包含子 Block?这些问题漏掉一个,下游开发者就会在真实项目里卡住两小时,翻源码、查构建日志、重装依赖,最后发现只是文档里少写了一行「header__nav 是独立 Block,不是 header 的 Element」。
最易被忽略的一点是:BEM 不保障结构安全,它只约定命名。工具如 postcss-bem 或 stylelint-selector-bem-pattern 可以校验格式,但无法判断 card__footer 该不该出现在 <footer> 标签里 —— 这得靠文档用一句话钉死。


















