BEM方法论疑问:能否在不同子块中复用同一元素类名?
嘿,刚上手BEM确实容易遇到这类归属模糊的疑问,我来帮你理清楚~
首先直接给结论:你当前复用container__title的做法不完全符合BEM的规范,核心问题是元素的归属逻辑不清晰,下面具体拆解:
为什么当前写法有问题?
BEM的核心逻辑是「块(Block)- 元素(Element)- 修饰符(Modifier)」,其中元素是块的组成部分,命名必须明确指向所属的块(格式为Block__Element)。
看你的代码:
<div class="container"> <div class="container__block-2"> <h1 class="container__title container-title">block2</h1> </div> </div>
这里的container__title被放在了container__block-2内部,就会产生歧义:这个标题到底是属于最外层的container块,还是属于container__block-2这个元素?
按照BEM的规则,如果它是container的直接元素,就不应该嵌套在container__block-2里;如果它是container__block-2的内部元素,正确命名应该是container__block-2__title,而不是跳过层级直接用container__title。这种模糊的命名会破坏BEM的可读性和维护性。
符合BEM规范的两种解决方案
根据你的需求(给不同区块的h1设置不同边距),推荐两种合规的写法:
方案1:使用修饰符(Modifier)
如果container__block-1/2/3是同一种元素,只是样式有差异,给它们添加修饰符,再通过修饰符控制内部标题的样式:
<div class="container"> <div class="container__block"> <h1 class="container__title">block1</h1> </div> <div class="container__block container__block--variant-2"> <h1 class="container__title">block2</h1> </div> <div class="container__block container__block--variant-3"> <h1 class="container__title">block3</h1> </div> </div>
对应的CSS:
/* 基础标题样式 */ .container__title { padding: 8px; margin: 0; } /* 针对不同区块的标题调整边距 */ .container__block--variant-2 .container__title { margin-top: 16px; padding-left: 24px; } .container__block--variant-3 .container__title { margin-bottom: 12px; padding-right: 18px; }
或者直接给标题添加修饰符,更直接:
<h1 class="container__title container__title--large-margin">block2</h1>
CSS:
.container__title--large-margin { margin: 16px 0; padding: 12px; }
方案2:明确元素归属
如果标题确实是container__block-2的专属内部元素,就用嵌套元素的命名规则,同时可以提取通用样式类复用:
<div class="container"> <div class="container__block-1"> <h1 class="container__block-1__title title--base">block1</h1> </div> <div class="container__block-2"> <h1 class="container__block-2__title title--base title--custom-margin">block2</h1> </div> </div>
这里title--base是通用样式类,title--custom-margin是差异化样式,既符合BEM的归属逻辑,又能复用代码。
总结
BEM允许复用类名,但前提是类名的归属逻辑清晰。你当前的写法模糊了元素所属的块,所以不太合规。用修饰符或者明确元素归属的方式,既能实现你的样式需求,又能符合BEM的设计初衷。
内容的提问来源于stack exchange,提问作者Asking

