BEM是大型项目唯一不靠运行时兜底的样式契约,因其通过block__element--modifier命名即契约,实现模块归属、从属关系与状态三重锚定,天然隔离样式并适配微前端/SSR。

因为现代浏览器再快,也拦不住人写 .card .price;CSS-in-JS 再智能,也救不了后端模板里漏掉的 JS 执行时机——BEM 不是过时的命名习惯,而是当协作、复用、直出 HTML 这三件事同时发生时,唯一不靠运行时兜底的样式契约。
为什么原生 CSS 嵌套(@nest)没让 BEM 失效
原生嵌套解决的是书写便利性,不是作用域问题。写 .user-card { &__avatar { } } 生成的是 .user-card__avatar,它依然依赖 BEM 的语义结构;但若写成 .user-card { .avatar { } },哪怕在原生嵌套语法下,也会编译出带空格的选择器,触发浏览器逐层回溯,且破坏模块边界。
- 原生嵌套不自动校验 BEM 合法性:
& .user-card__badge是合法语法,但产出的是危险的空格选择器 - @scope 规则目前仅支持顶层作用域,无法绑定到组件粒度,也不被 SSR 或微前端子应用的静态 HTML 消费
- DevTools 的 Computed Styles 面板里一眼就能看出有没有空格——有空格就说明 BEM 被绕开了,不管用了没用嵌套
为什么 Tailwind 或 CSS-in-JS 项目仍要保留 BEM 类名
Tailwind 管“怎么长”,BEM 管“是谁的”。纯 utility class 的 HTML 搜索困难、调试无上下文、无法反推组件位置。一个 product-card 类作为锚点,能让 grep -r "product-card" src/ 直接定位到组件目录,而 flex items-center p-4 则什么都说明不了。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
- CSS-in-JS 库(如 styled-components)生成的哈希类名(
sc-bdVaJa)对后端模板、审计、SEO 工具完全不可读 - BEM 类名是唯一能在 Java/PHP 模板、Figma 导出、埋点系统中跨角色对齐的标识符
- 推荐模式:
<div class="product-card"><div class="product-card__image">...</div></div>+ Tailwind 控制内部表现
为什么 CI 拦截比文档更重要
BEM 的失效从不发生在第一次写错的时候,而发生在第 27 次没人拦住的时候。手滑一次 user-card__avatar 被塞进 article 容器,或漏写基础块样式导致 user-card--loading 单独存在,整个模块的样式契约就松动了。
立即学习“前端免费学习笔记(深入)”;
- 必须启用
stylelint-selector-bem-pattern并设为error级别,拦截button--primary--large、avatar--xs、.card .title - 构建后跑
grep -r "\.[a-z]\+ \.[a-z]" dist/,揪出所有残留空格选择器 - 目录结构强制对齐:
/components/user-card/user-card.css里出现.product-grid__item就该立刻 fail
真正难的不是记住 __ 和 -- 怎么打,而是在每次加修饰符前问一句:这个状态是否可枚举、是否与其他修饰符正交、是否脱离块就失去意义——这种判断没法交给工具,只能靠人盯住边界。

















