开源项目类名必须自解释,因无人提供上下文,如user-card__avatar明确归属、角色与状态,支持精准搜索、跨角色协作及构建产物隔离,杜绝撞车与误改。

因为大型开源项目没人给你讲上下文,card__title 这种名字自己就能说清“这是 card 组件里的标题”,而 .title 或 .card-title 在 GitHub 上一搜就撞车,改一个地方,三个子模块同时崩。
为什么开源项目里类名必须“自解释”
没人会为你写文档说明 user-card__avatar 属于哪个组件、能不能单独复用。BEM 把“谁的样式、作用在哪、当前什么状态”三件事硬塞进类名里:user-card 是块(归属),__avatar 是元素(角色),--xs 是修饰符(状态)。GitHub 搜索 grep -r "user-card__" . 一瞬间就能定位全部模板、样式、JS 逻辑,而不是靠猜或翻十个文件。
常见错误现象:.modal .close 这种写法在 PR Review 时根本看不出是哪个 modal;换成 checkout-modal__close--hovered,连非前端协作者(比如 PHP 工程师)都能看懂用途、审计能追溯、CDN 缓存可命中。
- 块名必须业务语义化:
product-card✅,box❌ - 禁止跨块使用元素:
card__header不能出现在article容器里 - 修饰符只描述稳定可枚举的状态:
button--disabled✅,button--left❌(响应式下位置会变)
为什么 BEM 能扛住微前端和 SSR 场景
微前端子应用或 Java/PHP 模板直出 HTML 时,JS 还没执行,CSS-in-JS 的 css-1a2b3c 根本没机会生成——此时 search-form__input 就是唯一契约。它不依赖运行时,后端工程师能读、审计能追、构建产物里不会出现空格选择器。
常见错误现象:多个子应用共用一份 CSS,都定义了 .input,结果搜索页的输入框圆角被结账页的样式吃掉;换成 search-form__input 和 checkout-form__input,天然隔离,互不干扰。
- 所有规则必须单类名触发:
.search-form__input✅,.search-form .input❌ - 禁止嵌套选择器:DOM 结构哪怕被其他子应用加了个 wrapper,样式照样生效
- 构建后可用
grep -r "\.[a-z]\+ \.[a-z]" dist/快速揪出残留的空格选择器
为什么伪 BEM 比不用 BEM 更危险
真正让开源项目失控的,不是没用 BEM,而是用了但没守底线:比如 HTML 写了 class="card card--featured",CSS 却只定义了 .card--featured,删掉修饰符整个组件就视觉断裂;又或者写出 button--width-200px,换单位就得新增 button--width-20rem,版本迭代时类名爆炸。
常见错误现象:card__header__title 违反 BEM 层级规则(元素不能嵌套元素),IDE 跳转失效、工具链无法校验;button--primary--large--disabled 看似省事,实则每个修饰符都失去独立性,主题系统没法按状态粒度接管。
- 伪 BEM:漏基础块样式,下游使用者一升级就视觉断裂
- 跨 Block 元素:
card__header__title❌,应拆成card__header+header__title(后者升格为 block) - 修饰符含具体值:
--small、--red、--2x这类命名在响应式或主题切换时必然卡死
真正难的不是敲出 __ 和 --,而是每次写 user-card__avatar--loading 时,得确认:这个 avatar 真属于 user-card?这个 loading 描述的是组件固有状态,还是临时补丁?一旦松动,协作成本就从分钟级跳到小时级。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











