block名必须业务语义化,如product-card、search-form,确保项目内天然唯一、避免样式污染;禁用box、container等通用词,因其易重复导致.class__title跨组件误匹配。

Block名必须业务语义化,不能用通用词
唯一性不是靠“起个生僻名”实现的,而是靠 Block 名天然不可重名——它得来自真实业务模块。比如 product-card、search-form、user-avatar 这类名字,在项目里不会重复;而 box、container、item 会在多个组件里出现,导致 .box__title 被意外匹配、样式污染。
实际开发中容易踩的坑:
- 目录是
/components/product-card/,但类名却写成.card—— 失去路径与命名的映射关系,唯一性失效 - 为图省事用
modal当 Block 名,结果弹窗、提示框、确认框全叫modal,修饰符--success和--error混在一起,根本分不清归属 - 把 Block 名写成带状态的,比如
active-tab—— 它不是独立组件,只是tab的一种变体,应写作tab--active
Element 只允许一级嵌套,禁止深层结构
BEM 不允许 .block__element__subelement 这种写法,因为这破坏了 Block 的独立性,也模糊了元素归属。真正属于 Block 的子级,就该是一层 __ 关系。
常见错误现象:
-
.card__content__title—— 实际上title是card的直接视觉子元素,应写作card__title -
.header__nav__link——nav本身已是独立 Block,不应作为header的 element;正确做法是拆成两个 Block:header和nav,各自管理自己的__link - 用标签名当 element 名,比如
.card__div或.card__span—— 元素名必须语义化,card__image、card__price才对
Modifier 必须绑定到明确的 Block 或 Element
修饰符不是独立存在的一类类名,它必须回答“它修饰的是谁?”这个问题。否则就是全局污染源。
可接受的写法:
-
nav-item--active✅(修饰nav-item这个 element) -
product-card--large✅(修饰整个 block) -
product-card__image--rounded✅(修饰具体 element)
典型错误:
-
is-active❌(没归属,谁 active?页面?按钮?表单项?) -
btn--left❌(位置类在响应式下失效,且语义不明确,“左”相对于谁?) -
card__title--dark但card本身没有--dark修饰符 —— 元素级 modifier 应依赖块级状态,否则逻辑断裂
为什么不能靠父选择器补救唯一性
写 .product-list .product-card__title 看似更安全,实则等于放弃 BEM 封装性。这种写法让样式强依赖 DOM 结构,一旦 HTML 层级变化,CSS 就失效。
真实影响包括:
- 组件挪到新页面时,必须连同
.product-list一起搬,否则.product-card__title样式不生效 - 编译后 CSS 被其他项目引用,
.product-list可能根本不存在,整条规则作废 - 多人协作时,有人改了父容器 class 名,没人意识到会牵连子元素样式,问题难以追溯
真正难的不是记住 __ 和 -- 的写法,而是每次新建组件时,能否坚持用业务实体命名 Block,并拒绝“先起个短名,后面再重构”的诱惑——这是唯一性落地的临界点,也是多数团队半途放弃 BEM 的地方。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











