BEM用__和--而非.或-,因浏览器匹配时.card__title可哈希一次命中,而.card .title需向上回溯;且__和--是PostCSS、Stylelint等工具链识别块/元素/修饰符的唯一契约,替换将导致自动化失效。

浏览器匹配效率直接取决于类名是否为单字符串
写 .card__title 和写 .card .title 看似只差一个空格,但 CSS 引擎处理方式完全不同:.card__title 是哈希表一次命中;.card .title 需遍历所有 .title 元素,再逐个向上查父节点是否含 .card。DOM 节点越多,性能差距越明显。
常见错误现象:
- 在 Sass 中误写
& .card__subtitle(带空格),编译后变成.card .card__subtitle,彻底破坏 BEM 单类名优势 - 把
.header__logo复用到footer里却不抽成独立块,导致语义错位、样式泄漏
工具链识别依赖双下划线和双连字符的唯一性
__ 和 -- 不是“好看”或“风格统一”的问题,而是 PostCSS 插件、Stylelint 规则、VS Code 类名跳转等功能的识别基础。一旦换成 _ 或 -,工具就无法区分哪段是块、哪段是修饰符。
例如:
-
button--loading可被 IDE 自动补全、被 lint 规则校验状态合法性 -
button-loading或button_loading会被当成普通单词拼接,修饰符漏检率接近 100% - Vite 构建时若开启
cssnano的mergeLonghand,button__icon button__icon--hidden可能被压缩成button__icon,直接丢失修饰符
嵌套层级失控往往源于混淆了 DOM 结构与语义边界
BEM 明确禁止三层及以上命名,比如 user-card__content__avatar__badge。这不是“写太多 __”的问题,而是把 HTML 嵌套当成了语义层级——BEM 的元素必须直接隶属于块,不承认父子元素关系。
正确做法是:
- 优先提取为独立块:
badge+badge--unread,再组合使用 - 若必须保留在卡片内,重命名语义:
user-card__avatar-badge(表示“头像上的徽章”,不是“内容里的头像里的徽章”) - 禁用
user-card__content-avatar-badge:中划线无法被 BEM 工具识别,会被误判为块名
修饰符命名不当会引发响应式失效和维护黑洞
-- 只能用于描述稳定、可枚举的状态,不能塞具体值或临时布局信息。
典型错误:
-
card--width-300px❌ —— 像素值会随设计迭代失效,应抽象为card--compact✅ -
button--left❌ —— 响应式下位置可能变化,不属于稳定状态 -
tab--enter-active tab--leave-active✅ —— 多个动画状态必须分拆,避免 JS 拼接类名导致不可控
最常被忽略的一点:__ 和 -- 是机器可解析的契约,不是人眼审美选择。删减、替换或手写模糊变体,短期省事,长期会让样式不可定位、不可自动化、不可协作。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











