应将 card__body__list__item 拆为独立 Block list 或 list--in-card,因其具备复用性、独立状态和行为,违反 BEM 元素不可嵌套原则,需提级为 Block 并用 mix 或自定义属性微调样式。

遇到 card__body__list__item 这种类名,说明结构已失控
浏览器不会报错,但这个类名已经违反 BEM 最基本原则:Element 只能属于一个 Block,且不能嵌套。它实际隐含了 DOM 路径依赖,一旦 card__body 改成 card__section,所有 card__body__list__item 样式静默失效。
这不是命名风格问题,而是组件边界模糊的信号——你本该在 list 出现的地方,就把它定义为独立 Block。
- 删掉中间层:去掉
__body和__list,把list提级为独立 Block,类名改为list或带上下文的list--in-card - 禁止 SCSS 中写
&__body { &__list { &__item {} } },只允许单层&__item直接挂在.list下 - HTML 中对应节点应挂两个类名:
card__body+list list--in-card,而非强行塞进一个 Block 的层级里
什么时候必须拆出新 Block,而不是继续用 __ 扩展
判断标准非常具体:这个 UI 片段下次出现在另一个页面时,你愿不愿意直接复制粘贴这段 HTML 和 class?如果答案是“要改一堆类名”或“得重写样式”,那它就不该是子元素,而该是 Block。
-
status-badge在用户卡片、日志表格、弹窗中都出现 → 必须是独立 Block,用status-badge--pending等 Modifier 控制状态 -
action-button在列表项、表单底部、卡片操作区共用 → 不该叫user-list__item__action,而应复用action-button action-button--sm -
dropdown有自己显隐逻辑、过渡动画、键盘行为 → 永远不该是nav__item__dropdown,而应是独立dropdown实例,嵌在nav__item内部即可
多个子元素共用同一状态,别堆 --is-loading 到每个 Element
写 card__header--is-loading card__body--is-loading card__footer--is-loading 看似“符合 BEM”,实则重复冗余,且 JS 控制成本翻倍。状态外溢是类名膨胀的主因之一。
立即学习“前端免费学习笔记(深入)”;
- 把状态提升到父 Block:用
card--is-loading统一标记 - CSS 中用选择器批量控制:
.card--is-loading .card__header、.card--is-loading .card__body - Modifier 只保留布尔型或枚举值:
--disabled✅,--in-dashboard❌(位置描述不可复用)
想复用按钮但又需要微调样式,用 mix 而不是 __ 嵌套
卡片里的操作按钮,既要有卡片专属边距/圆角,又要保持按钮通用交互逻辑——这时候硬写 card__action-button--primary 是错的。BEM 官方支持 mix,这是合法解法。
- HTML 写法:
<button class="card__action button button--primary"> - 样式作用域靠
:where()或 scoped CSS 隔离,避免.button影响.card__action - 前提是这个按钮在卡内确实需要不同禁用态、不同 hover 行为;如果只是尺寸/颜色微调,优先用 CSS 自定义属性控制,比如
style="--btn-padding: 8px 16px"
__ 前,没问一句“它有没有自己的状态、行为或复用场景”。一念之差,就从可维护组件滑向 DOM 路径快照。


















