应将有独立状态、行为或复用场景的子结构升为独立Block;Modifier须离散互斥且≤5个;状态类应提升至父Block统一控制,避免重复和外溢。

别缩写类名,缩写 user-card__avatar--size-lg → uc-avt--l 会直接让 DevTools 里看不出组件归属、构建工具误删、新人完全无法理解。真正该动刀的是组件边界、状态表达和 Modifier 使用方式。
怎么判断一个子结构该拆成独立 Block 而不是留作 __element
核心就一条:它有没有自己的状态、行为或复用场景?有,就必须升为 Block。
-
status-badge出现在用户列表、订单卡片、通知弹窗里 → 应该是独立 Block,不是user-card__status -
price-tag有自己的颜色逻辑、点击反馈、加载动画 → 不该依附于product-card命名 -
form-field在登录页、筛选栏、设置表单都用 → 它和search-form是协作关系,不是从属关系 - 一旦出现三层下划线(如
header__nav__item__link),说明已违背 BEM 原则:Block 应是独立单元,__只描述直接子元素
Modifier 堆叠失控时该怎么收口
像 button--theme-primary--size-xl--variant-outline--is-loading 这种类名,问题不在长度,而在把配置逻辑全塞进了 HTML —— 后期改一个值就得全局搜索替换,且 PurgeCSS 很难安全识别。
- Modifier 必须离散、互斥、可枚举;总数建议 ≤ 5 个(如
button--primary、button--disabled、button--sm、button--lg、button--outline) -
--size-xl和--theme-dark这类只控制间距、颜色的值,应交给 CSS 自定义属性:button+style="--btn-padding: 16px 32px; --btn-bg: #007bff;" - 布尔型状态(如
--is-loading)可以保留,但必须和 Block 类名共存:user-card__avatar user-card__avatar--is-loading,不能单独出现 - 禁止形容词堆叠:
button--very-big-and-centered是反模式
多个子元素共用同一状态时,为什么不能各自加 --modifier
写 dashboard__header--loading + dashboard__chart--loading + dashboard__list--loading 看似直观,实则重复、难维护、易漏改。状态外溢是类名膨胀最隐蔽的推手。
立即学习“前端免费学习笔记(深入)”;
- 正确做法是提升到父 Block:
dashboard--is-loading,再用选择器批量控制:.dashboard--is-loading .dashboard__header - 需配合作用域隔离,推荐用
:where()或 scoped CSS 防止污染其他模块 - 如果 JS 层需要监听状态变化,统一在
dashboard元素上操作 class,比分散管理 5 个子元素更可靠 - 这种提升不只省字符,更让“加载中”这个语义真正属于页面上下文,而非某个视觉片段的附属品
最容易被忽略的一点:类名变长往往发生在页面容器(如 dashboard-page)和功能组件(如 user-card)混为一谈时。你写的不是 CSS,是组件职责的说明书——敢不敢把一个“看起来很像子元素”的东西单独拎出来当成 Block 维护,比怎么缩写重要得多。


















