bem通过字符串精确匹配替代结构匹配,确保样式隔离与高效渲染;禁止空格选择器和非法嵌套,强制使用__/--语法锚点,并要求modifier必须与基础类共存。

因为 BEM 把样式生效的条件从“结构匹配”变成“字符串精确匹配”,.user-card__title 只对带这个完整类名的元素生效,改它不会触发 .profile-card__title 或 .card__title 的样式变化。
浏览器只认类名字符串,不认 DOM 层级
BEM 不依赖嵌套选择器,所以 .user-card .title 这种写法本身就是违规。浏览器匹配 .user-card__title 时直接哈希查找,不回溯父级;而一旦用了空格选择器,就得先找所有 .title 元素,再逐个检查祖先是否含 .user-card——DOM 越深、同名元素越多,越容易误中或漏掉。
- 常见错误现象:
margin越调越大、调试时发现样式来自完全无关的 CSS 文件 - 真实场景:把
product-card组件挪到搜索页,只要 HTML 里保留class="product-card__title",样式就照常生效,不用动任何 CSS - 性能提示:DevTools 的 Computed Styles 面板里如果看到规则来源是
.card .title(带空格),说明已破坏 BEM 隔离,应立即修正
__ 和 -- 是硬性语法锚点,不是风格偏好
工具链(如 stylelint-selector-bem-pattern)靠这两个符号识别 BEM 结构。写错就等于关掉所有防护,比如 .card-header--large(漏一个 _)、.button__icon_error(用单 _ 代替 --)、.card__title--small--dark(嵌套修饰符)都会逃过校验。
- CI 中必须跑
npx stylelint "**/*.{css,scss}",否则人工 Review 几乎无法发现这类低级但致命的拼写错误 - SCSS 中只允许
&__avatar和&--loading,禁止.user-card { .avatar { } }这种嵌套,否则编译出带空格的选择器 - JS 动态拼接类名时,手写
className={`user-card__avatar--${size}`}极易因大小写或连字符漏写导致线上失效,应统一用cn()类函数封装
Modifier 必须和基础 Block/Element 共存
.button--primary 单独存在是无效的——它只是状态补充,不是新组件。CSS 规则通常只定义 .button--primary 的差异部分(比如颜色),基础样式(padding、border)全在 .button 里。漏写基础类,整个样式链就断了。
- 常见错误现象:写
class="btn--loading",但 CSS 里只有.btn--loading规则,没写.btn基础样式,结果加载态完全不显示 - 正确写法:
class="button button--loading",确保基础类始终存在 - 搜索影响范围时,
grep -r "button--loading"可能返回零结果,因为实际生效靠的是button+button--loading两个类共存,只搜修饰符会漏掉关键上下文
真正容易被忽略的是:BEM 的隔离能力完全建立在“类名字符串可预测、可静态定位”之上。一旦在 SSR 场景下用 useId() 或随机 hash 生成类名,服务端和客户端渲染出的字符串不一致,就会触发 hydration mismatch——这不是 BEM 的问题,而是破坏了它最根本的前提。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











