bem 通过 block__element--modifier 命名明确样式归属、层级和状态,提升可读性与协作效率。header__logo--dark 比 logo-dark 更清晰表达模块、元素与状态;禁止多级嵌套如 card__content__header__title,element 不得嵌套 element;modifier 应表语义状态而非表现细节,如 button--disabled ✅、button--red ❌;js 操作须严格匹配类名,工具链保障命名契约不被破坏。

直接看类名就能判断样式归属、层级和状态,不用翻 HTML 或 JS 文件——这是 BEM 能给阅读体验带来的最实在提升。
为什么 header__logo--dark 比 logo-dark 更容易读
类名里没写 header,你就得点开 HTML 确认这个 logo-dark 是全局暗色 logo,还是仅用于页头的变体;而 header__logo--dark 一次性说清三件事:它属于 header 这个模块、是其 logo 元素、当前处于 dark 状态。
- 常见错误现象:
.user-card-avatar或.avatar-user-card——分隔符缺失或顺序混乱,stylelint-selector-bem-pattern校验不过,协作时靠猜 - 语义错位比性能问题更拖慢排查:
.btn-primary出现在弹窗里被意外覆盖?.button--primary直接告诉你这是按钮组件自身的主色调变体 - 浏览器 DevTools 里搜
card__title,立刻定位到对应 CSS 文件,不用在一堆.title中人工过滤
card__content__header__title 这种写法为什么必须禁止
BEM 只允许一层 __,多级嵌套不是“更细粒度”,而是结构失控信号。它说明你正在用命名模拟 DOM 层级,反而破坏了 Block 的独立性。
- 正确做法:
card__title(标题直属于 card)或另起一个独立titleBlock(如果该标题逻辑复杂、需跨场景复用) - Element 必须依附 Block,不能嵌套 Element:
card__header__title❌,card__title✅ - Sass 嵌套中尤其危险:
.card { &__header { &__title { } } }编译出非法类名,但语法无报错,人眼难察觉 - 真正需要多层语义时,应拆成组合:
<card><header><title></title></header></card>→ 对应card+header+title三个独立 Block
Modifier 写成 button--red 还是 button--primary
修饰符回答的是“它现在处于哪种可预期的状态”,不是“我要加点红”。颜色、尺寸、位置这些表现细节,应该由 Modifier 所代表的语义决定,而不是直接拼进名字里。
- 合理:
button--disabled、form-field--error、user-card--compact(compact是一种明确的设计状态,不是纯尺寸) - 错误:
button--red(表现而非状态)、user-card--small(尺寸应交由媒体查询或响应式类控制) - 更隐蔽的坑:
card__title--large✅(修饰元素合法),但card--featured__title--large❌(修饰符不能跨层作用于元素) - JS 动态操作类名时必须严格匹配:
el.classList.add('button--loading'),别拼'button--' + state,易漏空格、错顺序、难调试
最常被忽略的点是:BEM 的可读性不来自“名字够短”,而来自“名字自带上下文”。工具链(如 stylelint-selector-bem-pattern、VS Code snippet)能缓解输入成本,但一旦允许 __ 和 -- 的数量或位置出错,整套契约就失效了——人脑不会自动纠错,但浏览器会照单全收。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











