bem通过__和--明确归属、层级与状态,写错符号或漏class即失效;判断block需看删父级后是否独立可复用;css必须扁平输出,禁止后代选择器;修饰符须精准绑定主体并语义化;js类名拼接应封装防错且白名单校验。

直接说结论:BEM不是给类名加长,而是用__和--把归属、层级、状态锁进名字里——写错一个符号,样式就失效;漏一个class,结构就崩。
怎么判断该建 block 还是 element
核心就一条:删掉父级后,它还能不能独立存在、有没有复用价值。
-
.search-form是 block:首页、弹窗、商品页都能用,有完整语义和样式边界 -
.search-form__input是 element:离开search-form就没意义,没独立样式上下文 -
.logo如果在页头、页脚、邮件模板里都用同一套样式,它就是 block;写成.header__logo反而限制复用 - 常见错误:
.section-2、.wrapper、.container都不是 block——它们只是布局占位符,没功能含义
SCSS 里嵌套怎么写才不破坏 BEM
BEM 的 CSS 必须扁平输出,任何空格连接的选择器(如 .card .card__title)都是反模式,会破坏封装性、无法溯源、且 lint 工具报错。
- ✅ 正确:
.card {&__title { font-size: 1.2rem; }&--featured { background-color: #f0f8ff; }} - ❌ 错误:
.card {&__content {&__icon { /* 编译出 .card__content .card__content__icon */}}}——这生成了后代选择器,也违反了“元素只直属于 block”原则 - 遇到“元素里的图标”,别硬套
.card__content__icon,优先拆新 block:.status-badge或.icon,再通过组合使用:.card__content .status-badge
Modifier 写错位置或命名,后果比你想象的严重
修饰符不是装饰贴纸,它绑定的是具体主体。挂错地方或起模糊名,会让主题切换、状态管理、CI 检查全乱套。
- ❌ 禁止:
.button--primary__text(修饰符不能跨级修饰元素) - ✅ 正确:
.button--primary(块级修饰符),或.button__label--hidden(元素级修饰符) - 命名必须表达意图:
--disabled✅,--red❌;--large✅,--v2❌ - 多个修饰符可共存:
.button--primary--disabled,但前提是逻辑正交(比如颜色和禁用状态不冲突)
JS 动态拼接类名时最容易翻车的三个点
手拼字符串看着快,上线后常因大小写、连字符、空格缺失,在 Linux 构建环境直接挂掉。
- ❌ 危险写法:
className={`button button--${variant} ${hasIcon ? 'button__icon' : ''}`—— 缺空格、button__icon脱离 block、无防错 - ✅ 推荐封装工具函数:
const cn = (e, m) => `${BLOCK}${e ? '__' + e : ''}${m ? '--' + m : ''}`,调用cn('input', 'disabled')得到search-form__input--disabled - 所有 modifier 值必须白名单校验,避免用户输入
button--onmouseover这类非法类名
最常被忽略的其实是分隔符本身:__ 和 -- 不是风格偏好,是 lint 规则、VS Code 插件、构建时样式提取的硬性锚点。少一个下划线,stylelint-selector-bem-pattern 就报错;多一个空格,CSS 就不生效——它不靠人眼识别,靠机器校验。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











