正确做法是用 comment--nested 修饰符标识嵌套评论,保持类名扁平;comment__reply__content 违反BEM原则,因 reply 非独立块,且导致权重过高、查询困难、复用性差。
如果直接使用 comment__reply ,就会与一级回复混在一起,尤其当回复仍可继续回复时。BEM并不支持“无限递归命名”,comment__reply__reply 这种命名方式既违背语义,也不便维护。
合理方式是由结构本身呈现嵌套层级,同时让类名保持扁平:
comment 作为最外层块,每条评论都构成独立块comment__content、comment__author 等名称只用于描述当前块中的元素comment 块,并通过修饰符区分状态:comment--nested
.comment > .comment,处理样式继承或缩进,而不是让类名形成嵌套comment__reply__content 这类包含三层的命名BEM 中的 __ 只能用来连接“块”与“直接子元素”,comment__reply__content 实际上暗示中间存在一个名为 reply 的块,但 BEM 规定每个块都应具有独立语义和复用能力。若 reply 无法作为独立 UI 单元使用,它便不应成为块,更不能充当命名链中的一环。
这种命名还会带来以下问题:
立即学习“前端免费学习笔记(深入)”;
.comment__reply__content 相较于 .comment--nested .comment__content 权重更高,后续难以覆盖)el.querySelector('.comment__reply__content'),可实际 DOM 中或许根本不存在 reply 这一元素节点replies 数据最终渲染的依旧是 comment 块,而非 reply 块comment--nested 如何使用修饰符才不会违背BEM原则修饰符用于描述同一个块的不同变体,comment--nested 表达的是“该评论块位于嵌套位置”。它不会改变块的本质,只会调整缩进、边框和字体大小等表现。
需要遵守的关键约束:
<div class="comment comment--nested">,不可添加到子元素上comment__author、comment__time,不能变为 comment--nested__author
comment--nested,再通过 CSS 后代选择器或由 JS 动态添加深度类,例如 comment--nested-level-2,进行细微调整,而不是修改 BEM 结构随着 DOM 层级加深,CSS 更容易发生意外穿透。例如 .comment__content p 可能既匹配顶层评论中的段落,也匹配嵌套评论中的段落。
建议采用以下组合策略:
:where() 降低权重::where(.comment--nested) .comment__content { padding-left: 24px; }
.comment--nested .comment__author { font-size: 0.9em; },不要只依赖块级修饰符comment 块内部的全部样式均以 .comment 开头,不依靠上下文,例如避免编写 .comment p,应改为 .comment__content p)--comment-nest-indent: 24px;,再由 JS 根据 depth 进行设置真正棘手的并不是类名如何命名,而是确保每个 comment 块在任何嵌套深度中都能保持视觉一致,同时不依据 DOM 深度判断样式。要做到这一点,必须从组件设计阶段解除样式对结构层级的依赖。