.btn--primary更可靠,因bem用块名(.btn)+双横线修饰符(--primary)明确语义归属,而.primary-btn形容词前置易致作用域误判;修饰符仅表状态/变体(如.btn--small),禁用位置描述(如.btn--mobile);子元素具复用性时应升格为独立块(如.price-tag);状态类需绑定块名(.btn.is-active)避免全局冲突;工具链可防手误,bem本质是组件接口契约。

为什么.btn--primary比.primary-btn更可靠
因为BEM强制把语义归属写进名字里,.btn是块(block),--primary是修饰符(modifier),一眼能分清“谁在被修饰”。而.primary-btn是模糊的形容词前置,既像修饰符又像独立组件,协作时容易误判作用域。
常见错误现象:.header-logo-active这类混合命名,在重构时没人敢动——它到底是.header的子元素?还是.logo的状态?还是个新组件?
- 块名必须是名词,比如
.card、.form、.nav,不能是.active-card - 修饰符用双横线
--,不是单横线或下划线,避免和子元素__混淆 - 修饰符只描述状态或变体,不描述位置或上下文,所以
.btn--mobile是错的,.btn--small才对
__子元素命名时,哪些层级该拆成新块
子元素(element)用双下划线__连接,比如.card__title、.card__footer。但一旦某个子元素具备复用性、独立样式逻辑或可能脱离当前块存在,它就该升格为独立块。
使用场景:一个.product-list里有多个.product-item,每个item里又有.price-tag——如果.price-tag在商品详情页、购物车、弹窗里都出现,那它就不该是.product-item__price-tag,而应是独立的.price-tag块。
- 判断标准:这个类是否会在其他DOM结构中重复使用?
- 性能影响:过度嵌套子元素名(如
.modal__content__header__title)会拖慢CSS选择器匹配,也违背BEM本意 - 兼容性无问题,但Webpack或Vite的CSS模块化方案里,过深的
__名可能增加哈希冲突概率
修饰符--和状态类is-混用时的坑
BEM规范本身不定义状态前缀,但团队常引入is-active这类JS驱动的状态类。问题在于:当.btn--primary.is-active和.btn--secondary.is-active共存时,.is-active的样式若没限定作用域,就会互相覆盖。
错误现象:.is-hidden全局生效,结果让.tooltip.is-hidden和.sidebar.is-hidden都失去过渡动画,因为动画属性被重置了。
- 推荐做法:状态类也绑定到块上,写成
.btn.is-active而非单独.is-active - 参数差异:修饰符
--是设计层面的静态变体(主题、尺寸),状态类is-是运行时动态切换的(展开/收起、加载中) - 不要让
.btn--primary.is-active依赖.is-active内部的color声明——它该由.btn--primary.is-active自己完整定义
工具链里怎么避免手写BEM出错
手动拼接.block__elem--mod极易漏掉下划线或横线,尤其嵌套深时。靠命名规范文档不如靠工具约束。
实操建议:
- VS Code装
EMO BEM插件,输入.btn[tab]自动补全.btn__text--large等常用组合 - PostCSS用
postcss-bem-linter检查是否出现.btn-primary这种非BEM写法 - 在CSS-in-JS方案(如Emotion)里,用
cx或clsx组合时,显式拆开块名与修饰符:clsx('btn', isPrimary && 'btn--primary'),别写成clsx(`btn${isPrimary ? '--primary' : ''}`)
最易被忽略的是:BEM不是命名洁癖,而是接口契约。当你发现要给.card__header__title加一个仅用于打印样式的--print修饰符,就得停下来问一句——这个标题是不是早该是个独立.heading块了?
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











