改用bem命名可避免样式崩坏:.user-card__title明确归属,禁用空格选择器和标签选择器,块名需语义唯一,修饰符用形容词,配合stylelint和工具链强制校验,新代码强制bem,旧代码冻结不扩散。

为什么改个 .title 会牵出三个页面的样式崩坏
因为传统写法把作用域藏在 DOM 结构里:.user-card .title 看似简洁,实则依赖父容器存在、依赖标签嵌套顺序、还可能意外匹配到其他模块的 .title。一旦有人把 <h3 class="title"></h3> 挪进弹窗组件,或者把外层 .user-card 改成 .profile-card,样式就静默失效——连控制台都不报错。
用 BEM 就是把“归属”写死:.user-card__title 只属于 .user-card 块,不关心它在哪、嵌几层、用什么标签。重构时删文件、换框架、拆组件,只要类名不变,样式就稳。
- 禁止写
.user-card .avatar这类空格选择器,必须显式写成.user-card__avatar - 禁用标签选择器(
button、p),全换成带块前缀的类名 - 块名必须语义唯一,拒绝
.section、.block这种泛义词
怎样让新人三分钟看懂 .header__logo--dark 的含义
靠命名自带层级 + 工具链强制校验。这个类名不是风格偏好,而是结构声明:header 是块(独立视觉单元),__logo 是它的元素(角色而非位置),--dark 是修饰符(状态变体,非颜色值)。
VS Code 装 Auto Rename Tag 插件后,改 HTML 里的 class="header__logo",CSS 文件中对应的 .header__logo 规则会自动同步重命名;再配 stylelint-config-bem,保存时立刻报错:Unexpected BEM element name "header__logo-inner"——说明你嵌套太深,该拆新块了。
- 写成
header_logo或header-logo,工具链直接失效:PostCSS 插件无法识别结构,stylelint不校验,IDE 不能跳转 - 修饰符必须用形容词或布尔值:
--disabled✅,--width-200px❌(违反“描述状态而非样式”原则) - 块名不能带样式描述:
.red-card❌,后续换主题就得全局重命名;应为.card--theme-red✅
React/Vue 里动态拼 className 为什么总漏掉一个下划线
手写模板字符串如 `${base}__${element}--${mod}` 是最大隐患:IDE 无法跳转、搜索失效、重构时漏改一处就埋雷。更糟的是大小写混用(Card__header vs card__header)在 Linux 构建环境直接导致样式丢失,且无任何报错。
正确做法是封装工厂函数或用 clsx 组合:
const bem = (block) => {
return {
el: (element) => `${block}__${element}`,
mod: (modifier) => `${block}--${modifier}`,
elMod: (element, modifier) => `${block}__${element}--${modifier}`
}
}
// 使用
<div classname="{bem('card').elMod('title',">...</div>
- 漏写 Block 前缀:
className={isFeatured ? 'featured' : ''}→ 应为product-card--featured - 连字符写错:
card__title--large(非法)→ 正确是card__title--large(注意双中划线只用于 modifier) - 修饰符永远叠加在块或元素上:
card--featured✅,单独用--featured❌(语义断裂,无法定位来源)
CI 流程里不跑 stylelint,BEM 就只是自我安慰
没工具链约束的 BEM,等于没有规则。默认 stylelint 对 .btn-primary、.modal-close-btn 全部放行。必须手动启用 stylelint-selector-bem-pattern 并严格配置:
"selector-bem-pattern": {
"componentName": "[a-z][a-zA-Z0-9]+",
"styleType": "bem"
}
- 加
ignoreSelectors排除伪类:["/^\..+:(hover|focus|active|disabled)/"],避免误报 - 禁用
fix: true—— 语义纠错没法靠机器做,自动修复可能生成.card__content__title这种非法嵌套 - CI 阶段必须跑
stylelint --config .stylelintrc.js src/**/*.css,不通过就阻断合并
真正卡住团队落地的,从来不是技术难度,而是老代码里 .user-list .item 和 .user-list__item 并存——开发者根本分不清该用哪个。策略只能是:停止新增非 BEM 类名,新功能、新组件、修改过的组件强制用 BEM,遗留代码不动但禁止扩散。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











