BEM禁止使用div.card等类型选择器,因其破坏样式作用域隔离——BEM依赖类名自身表达边界,混入标签名会使样式强耦合DOM结构,一旦HTML结构调整(如换用Flexbox),样式立即失效;必须仅用.card、.card__title、.card--loading等纯类名选择器。

直接用 div.card 或 button.card__action 会立刻让样式失去复用能力,且 DOM 一变就失效——BEM 的作用域必须只靠类名自身表达,不能依赖任何标签语义。
浏览器匹配时会把标签当硬性条件
写 div.card,浏览器就要求目标元素既是 div 又带 card 类;换成 section 或 article,样式直接不生效。这不是“可能出问题”,是必然断裂。常见错误包括:.header nav ul li a 改成 .header__nav ul li a,表面加了 BEM 前缀,实际仍卡在 ul/li 结构上,后续改用 Flexbox 列表就全挂。
真实使用场景中标签根本不可控
- UI 框架(如 Ant Design、Element Plus)内部常动态替换标签:按钮可能是
button、span或a,取决于type和href - 服务端渲染或微前端场景下,同一组件在不同子应用里可能被包裹不同容器标签
- 无障碍增强时,
role="button"的div可能替代原生button,但样式不能因此丢失
Modifier 和 Element 的语义会被标签污染
.card__title:hover 合法,因为它是基于类名的交互反馈;但 h2.card__title 就把语义混进了标签层级——万一设计系统要求标题在某些页面用 h3,你就得同步改 CSS、JS 查询逻辑、测试断言三处。更严重的是:button.card__action 看似“强化语义”,实则让 .card__action 失去独立性:它不再表示“卡片里的操作按钮”,而变成“只有 button 标签才生效的操作区域”。
工具链和协作成本会指数级上升
stylelint 插件 stylelint-selector-bem-pattern 默认拦截含标签的选择器;VS Code 的 BEM 补全插件对 div.card__content 不响应;团队 Code Review 时,没人能快速判断这个 div 是语义必需,还是历史残留。真正难处理的不是写错一次,而是某人偷偷加了个 input.form-field,结果三个月后重构表单时,发现所有校验逻辑都绑死在 input 上,无法迁移到自定义输入框组件。
立即学习“前端免费学习笔记(深入)”;


















