bem文档是模块契约说明书而非类名列表。需明确block物理边界(如button必须是独立dom节点)、三名一致(button.vue→button)、element层级约束(button__text仅限直接子节点)、modifier叠加规则与冲突警告,并杜绝嵌套element、大小写混用等错误。

直接说结论:BEM文档不是类名列表,而是模块契约说明书。写错位置、漏写叠加规则、用错连接符,都会让下游开发者在真实项目里卡住两小时——而且查不出问题。
怎么写清 Block 的物理边界和复用契约
文档里只写「按钮用 button 作 Block」远远不够。必须明确:
-
button必须是可独立渲染的 DOM 节点(比如<button class="button"></button>或<div class="button">),不能只是包裹用的 <code><div> <li>文件名、组件名、Block 类名三者必须严格一致:<code>Button.vue→button,不是btn或ui-button - 如果某个视觉单元(如
icon)在按钮、导航、弹窗中都出现且行为一致,它就必须是独立 Block,不能塞进button__icon -
button__text只能是button的**直接子节点**,中间不能隔<span></span>或<div> <li>禁止出现 <code>button__text__highlight—— Element 不允许嵌套 Element,这是结构越界信号 - 设计稿里若出现“带图标的按钮文字”,不能靠嵌套解决,而应拆成并列 Element:
button__text+button__icon -
button--primary和button--disabled可叠加,但前提是 CSS 规则不依赖选择器权重(即必须用.button--disabled { },而非.button.button--disabled { }) -
button--large和button--small互斥,文档需加 ⚠️:“二者不可同时使用,否则尺寸定义冲突” - 禁止出现
button__text--large——--只能作用于 Block 或其直属 Element,不能降级到子元素内部 -
button--icon匹配的是“一种叫 icon 的按钮”,你要改的其实是按钮里的图标——得用button__icon -
dialog__header__title是非法结构,应为dialog__title;BEM 工具不会报错,但团队 grep 搜不到dialog__title,协作链就断了 -
button--primary__icon解析失败,BEM 工具直接忽略,样式白写
常见错误现象:文档写“card__header 是卡片头部”,但没注明它是否允许嵌套 card__title;结果开发者写了 <div class="card__header">
<h2 class="card__title">,样式却失效——因为 <code>card__title 实际只接受 card 直接子节点。
Element 文档必须标注 DOM 层级约束
BEM 的 __ 不表示 DOM 嵌套深度,但 Element 在 HTML 中的位置是有硬约束的。文档需明确:
典型翻车点:设计师给的切图里 header__nav 下有 nav__item,文档没说明 nav__item 是否属于独立 Block;前端按 BEM 理解为 header__nav__item,结果样式全挂掉。
Modifier 文档要写明叠加规则与冲突警告
修饰符不是开关贴纸,文档必须声明哪些能共存、哪些会打架:
错误示例不能只说“这样不对”,要附真实线索:比如写 class="button--primary button--large" 却没生效,实际是因为构建时 cssnano 合并了简写属性,把 padding: 12px 24px 压成了 padding: 12px 24px,但 button--large 的规则被覆盖了——这种线索比“命名错误”有用十倍。
类名拼写错误是落地第一道坎
__ 和 -- 写反不是风格问题,是直接导致样式不生效或意外覆盖。浏览器不报错,但人脑会卡住:
最隐蔽的坑是大小写混用:BtnPrimary 或 btnPrimary 都不合法,grep 搜不到,CI 检查也过不了——BEM 不处理大小写,但团队协作时它就是事实标准。











