BEM禁止div.card等类型选择器,因其将样式强耦合DOM标签,一旦HTML由div改为section或article,浏览器无法匹配而直接失效;必须仅用.card等纯类名确保作用域隔离与组件可移植性。

为什么 div.card 这类写法会直接破坏BEM封装性
BEM 的样式作用域完全靠类名自身表达,div.card 把标签名 div 当作必要条件,等于主动放弃组件可移植能力。一旦 HTML 改用 section 或 article 替代 div,样式立刻失效——这不是“没生效”,而是浏览器根本不会匹配它。
.card__title:hover 和 button.card__title 哪个更危险
后者更危险:button.card__title 是典型的标签+类组合,它隐含两个假设:元素必须是 button 标签,且必须有 card__title 类。但实际中,标题可能由 h3 承载,或按钮被封装成自定义组件(如 React 的 Button),此时样式彻底脱钩。
-
.card__title:hover合法:伪类只修饰已存在的 BEM 类,不引入新依赖 -
button.card__title违规:标签名绑定 DOM 结构,违反 BEM “样式与结构解耦”原则 - 连用标签选择器还会干扰 CSS-in-JS 和 SSR 场景,服务端渲染出的
span和客户端期望的button不一致时,触发 hydration mismatch
SCSS 里怎么一眼识别并拦截这类错误
工具链比人工检查可靠得多。在 stylelint 中启用 stylelint-selector-bem-pattern 插件,并配置 allowElements: false,它会直接报错:
/* ❌ 报错 */
.card__header nav ul li a { }
div.card { }
header .card__title { }
<p>/<em> ✅ 仅允许 </em>/
.card { }
.card<strong>title { }
.card</strong>title:hover { }
.card--loading { }</p>
- 禁止任何以标签、ID、属性开头的选择器(如
nav、#header、[data-foo]) - 允许伪类和媒体查询嵌套,但深度必须 ≤2(如
@media (min-width: 768px) { .card__title:hover { } }) - 团队共用同一份配置,CI 阶段自动拦截,比 Code Review 更早卡住问题
遇到第三方组件(比如 Ant Design)时怎么办
你不能改 .ant-btn 的类名,但可以守住自己的边界:
- 不写
.ant-btn直接覆盖,而是包一层 wrapper:<div class="my-form__submit-button"><button></button></div> - 用 wrapper 控制作用域:
.my-form__submit-button :deep(.ant-btn)(Vue)或.my-form__submit-button .ant-btn(纯 CSS) - 绝对避免
button.ant-btn这种写法——它把第三方类名和标签名双重锁定,后续 Ant Design 升级换标签就崩
真正难的不是命名规则本身,而是当别人写了 div.card 时,你得判断这是疏忽,还是他根本没意识到这个选择器已经让整个组件失去替换容器的能力。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











