bem规范要求block是语义完整、可复用的独立组件(如.card),而非视觉容器(如.section-2);element仅限block直接子部件(如.card__title),禁嵌套;modifier表达可预测状态(如.button--disabled),不绑定具体样式。

Block 是独立组件单元,不是视觉容器
BEM 的 Block 必须具备可复用性、语义完整性和独立样式作用域。它不是“随便一个 div”,也不是“页面里第几个 section”。比如 .card 合法,因为它是可复用的卡片组件;而 .section-2 或 .wrapper 不合法——它们只描述位置或结构,没有业务语义。
常见错误现象:.header__nav 看似合理,但如果 nav 在侧边栏也复用,那它就该是独立 .nav Block,而不是 header 的子元素。
- Block 名必须小写、连字符分隔(如
search-bar),避免驼峰或下划线 - 不能带父级语义:❌
.card__card-title,✅.card__title - 禁止仅靠 DOM 层级推导 Block:即使 HTML 里
<div class="card"> <h2 class="title">,也不能直接写 <code>.card .title—— 必须显式声明.card__titleElement 是 Block 的直接子语义部件,不嵌套
Element描述 Block 内部的组成部分,命名必须聚焦功能而非结构。它和 Block 之间只能有一层关系:Block→Element,不允许Block→Element→SubElement。常见错误现象:
.card__content__title或.menu__item__link这类三层命名,说明设计已超限——要么把title提升为独立 Block(如.heading),要么重新审视是否真需要这么深的语义层级。
PigX UI 前端开发下载PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
- Element 名不带 Block 名前缀冗余:❌
.card__card-header,✅.card__header - 所有 Element 必须是 Block 的直接子节点(HTML 层面不强制,但语义上必须可视为平级)
- 如果某个“子元素”在多个 Block 中复用(如图标、徽标),它就应该是一个独立 Block:
.icon,而非.button__icon或.card__icon
Modifier 表达状态或变体,不绑定视觉快照
Modifier是 Block 或 Element 的修饰,用于表达可预测的状态变化(如is-loading)、尺寸变体(--large)或主题变体(--dark)。它不是 CSS 属性的直译,而是业务意图的映射。常见错误现象:
.button--red或.card--big看似直观,但换品牌色就得全局搜索替换;.button--primary--disabled这种链式写法会破坏组合自由度。- Modifier 必须依附于 Block 或 Element 存在:✅
.button--disabled、✅.button__text--small,❌ 单独使用.--disabled - 多个 Modifier 并列使用,不嵌套:✅
.button--primary.button--disabled,❌.button--primary--disabled - 值必须可维护:✅
--loading、✅--featured,❌--v2、❌--new
SCSS 嵌套中怎么守住 BEM 边界
SCSS 的
&符号本身不违反 BEM,但一不留神就会生成后代选择器,破坏扁平类名契约。关键看编译后是否引入了空格。错误示例编译出
.card__title .icon,这等于退回到结构依赖的老路;正确写法只产出.card__title和.card__title--hovered这类扁平类名。- 安全写法:
.card { &__title { … } &--horizontal { … } } - 危险写法:
.card { &__title { .icon { … } } }→ 编译为.card__title .icon - 真需关联子节点样式,优先用属性选择器:
[data-icon="close"],比.modal__header__close更可控
- Element 名不带 Block 名前缀冗余:❌










