BEM简洁性源于边界清晰、命名克制、修饰符收敛,块名用单数职责名词(如card)、元素名聚焦功能(如card__header)、修饰符仅表达有限业务状态(如card--disabled),禁用视觉描述、标签名及像素级控制。

别把BEM当字符串拼接游戏——简洁不是靠缩写,而是靠边界清晰、命名克制、修饰符收敛。
块名和元素名必须用单数名词,不加视觉描述
常见错误是写user-card__user-info__name-text或big-header__title-text。这类命名既违反BEM层级原则(元素不能嵌套元素),又混入视觉判断(“big”“text”),导致复用困难、语义模糊。
- 块名只表达职责:
card、teaser、search-bar,不用user-card或big-card - 元素名聚焦功能而非样式:
card__header而不是card__big-header,search-bar__input而不是search-bar__textbox - 禁止用标签名或属性当类名:
card__div、card__data-id这种写法无法被PurgeCSS识别,也破坏语义
修饰符只用于有限业务状态,不用于像素级控制
button--primary、card--disabled、form-control--error是合理用法;button--size-small、card--padding-24、header--font-size-xl则是典型增肥操作。
- 修饰符必须有明确业务含义,且组合数量可控(通常≤5种)
- 尺寸、颜色、间距等应通过CSS自定义属性在
block层级统一定义,比如--card-padding、--button-font-size - 禁止一义多职:
button--primary-bg-blue-border-radius-8这种类名PurgeCSS无法推断使用场景,只能保守保留
避免跨块组合与动态拼接类名
构建工具(如PostCSS BEM插件或PurgeCSS)依赖静态可分析的类名格式。一旦出现class="card__item--${status}"或card__header nav__logo这类跨块混用,tree-shaking和自动清理就基本失效。
立即学习“前端免费学习笔记(深入)”;
- 一个HTML元素最多带一个
block名,其余只能是它的__elem或--mod - 第三方组件类名必须显式声明,比如用
van-button就得写class="van-button",不能靠JS自动注入 - Vue/React中动态拼接类名时,确保所有分支路径都覆盖完整BEM格式,否则部分类会被误判为未使用
BEM的简洁性不在字符长度,而在每个类名背后是否能回答清楚三个问题:它属于哪个独立模块?它在这个模块里扮演什么角色?它当前处于哪种可枚举的状态?答不上来,就该删掉或重划边界。


















