bem 的 __ 仅表示“直接属于”,非嵌套深度;-- 用于修饰符,_ 非法;块名应语义内聚,多层下划线暴露设计问题,需拆分为独立 block;modifier 描述静态状态而非 js 行为。

把__当成嵌套深度标记,而不是块-元素关系声明
初学者看到 menu__item__icon 这种写法,下意识觉得“三层结构就该三层下划线”,但 BEM 的 __ 只表示「直接属于」——menu__icon 和 menu__item 是平级的,都直接挂在 menu 块上。DOM 深度和类名层级无关,menu__icon 完全可以出现在 <menu></menu>
<ul><li><i></i></li></ul> 的最里层。
常见错误现象:user-card__content__avatar 被当成“合理嵌套”,实际它掩盖了设计问题:content 不是独立块,avatar 也不该是 content 的子元素语义,而是 user-card 的视觉组成部分。
- 正确做法:把深层节点提成独立 block,比如
avatar或user-avatar - 如果必须保留上下文(如图标颜色随菜单主题变化),可用
menu__item-icon(单下划线),但需全团队书面约定,不能随意用 - IDE 和 Sass 的
&__icon语法只识别一层__,多层会失效或报错
混淆_和--的语义边界
_ 在标准 BEM 中没有合法地位。你看到的 btn_primary 或 list_item,要么是旧项目遗留,要么是误读了连字符规则。BEM 官方、Sass 工具链、PostCSS 插件、@bem/react 全部只认 __ 和 --。
常见错误现象:button_primary 写出来后,&--hover 不生效,搜索 primary 找不到所有变体,重构时不敢批量替换——因为工具根本不知道它是修饰符。
- 修饰符必须用
--:✅button--primary、✅button__label--small - 多单词块名用短横线:✅
search-form,不是searchform或search_form -
button--loading-primary是合法组合,button_loading_primary是无效字符串,会被解析器忽略
用 DOM 结构反推类名,而不是按组件职责拆 block
很多人写到 page__section__list__item 就停不下来,以为“HTML 怎么嵌套,CSS 就怎么命名”。但 BEM 的 block 划分依据是「语义内聚性」,不是 DOM 层级。一个 page 块如果包含七八个不同功能区域,说明它已经失控。
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
常见错误现象:在 Card.module.css 里定义 .title,结果和 Header.module.css 的 .title 编译后不冲突,但开发者完全无法从类名判断样式归属。
- 遇到三级以上命名,第一反应不是“加下划线”,而是问:中间那层是不是该抽成独立 block?比如
user-list__item里的操作按钮,应是action-button,不是user-list__item__action - CSS Modules 的哈希名解决的是全局污染,BEM 解决的是语义可读性;两者必须同时存在才有意义
- 文件名、目录名、类名三者必须映射一致:components/Button/Button.module.css → 只允许出现
button、button__*、button--*
把 modifier 当成 JS 状态开关,而不是视觉/行为变体
button--loading 看似合理,但它把 CSS 类名和 JS 状态强耦合:一旦 loading 状态逻辑变更(比如改成 skeleton)、或需要支持服务端渲染的初始 loading,样式就难复用。BEM 的 modifier 应描述「是什么」,而不是「正在发生什么」。
常见错误现象:card--is-expanded、input--has-error,这类命名让样式依赖 JS 判断,破坏了 CSS 的静态可分析性。
- 推荐写法:✅
card--expanded(视觉状态)、✅input--error(已确认的错误态) - 禁止嵌套 modifier:
button--primary--large是错的;应为button--primary button--large,支持自由组合 - modifier 不改变结构,只改样式;如果要隐藏元素,用
button__icon--hidden,而不是删掉 DOM
className 前,有没有花半秒想清楚:它属于谁?它表达的是结构、状态,还是视觉变体?这个判断一旦松动,后面所有工具链、协作、重构都会连锁失准。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










