如何使用 BEM 正确设置元素的范围?

Posted

技术标签:

【中文标题】如何使用 BEM 正确设置元素的范围?【英文标题】:How to properly set an element's scope using BEM? 【发布时间】:2015-03-09 18:53:14 【问题描述】:

给定以下 BEM 树结构,其中存在五个嵌套级别:

collection-main__features-top__story__byline__author

根据 BEM 的命名约定,元素是块的一部分并且在它所属的块之外没有任何意义,那么命名 author 类的正确方法是什么?

由于author 在语义上与bylinestory 上下文相关,但在features-topcollection-main 块下毫无意义,那么最好的BEM 名称是什么?

collection-main__author
features-top__author
story__author (best?)
story__byline__author
byline__author

如果引入新的features 块会怎样?

collection-main__features-top__story__byline__author (target)
collection-main__features-bottom__story__byline__author

features-top__story__author
story--features-top__author (best?)

最后,如果添加了另一个collection 块并且我们想要为列表中的第二个作者元素设置样式会发生什么?

collection-main__features-top__story__byline__author
collection-main__features-bottom__story__byline__author (target)
collection-sub__features-top__story__byline__author
collection-sub__features-bottom__story__byline__author

我们会做这样的事情吗?

story--collection-main--features-bottom__author

一定有更好的选择。

【问题讨论】:

请显示您的数据输出。像collection-main: ["feature-item": story: author: '' ] 吗? 【参考方案1】:

BEM 禁止在 CSS 中的元素中放置元素! 您在 BEM 标记中犯了最典型的错误 - 编写 block__element__element。 您必须创建新块,而不是复制 DOM 树。

例如: 正确的 html

<div class='block'>
    <div class='block__elem1'>
        <div class='block__elem2'></div>
    </div>
    <div class='block__elem3'></div>
</div>

正确的 CSS:

.block 
.block__elem1 
.block__elem2 
.block__elem3 

如果您需要制作一个元素的元素,那么您需要制作一个新块或使用单个嵌套元素制作您的 bem-tree!

错误:

<div class='block'>
    <div class='block__elem1'>
        <div class='block__elem1__elem2'></div>
    </div>
</div>

正确#1:创建一个新块

<div class='block1'>
    <div class='block2'>
        <div class='block2__elem'></div>
    </div>
</div>

权利 #2:使用单个嵌套元素制作你的 bem-tree

<div class='block'>
    <div class='block__elem1'>
        <div class='block__elem2'></div>
    </div>
</div>

注意——你不能将元素放在 css 中的元素中,但是你可以并且应该将元素中的元素放入 html 中! DOM-tree 和 BEM-tree 可以不同。

不要写奇怪的名字,把元素名放在块名里!

错误:

.block 
.block-elem1 
.block-elem1__elem2 

因为当你尝试移动方块时,你会遇到奇怪的名字问题:

<div class='other-block'>
    <div class='block-elem1'></div>
</div>

嵌套的 html 元素是一个 DOM 树。 您编写的类的名称是 BEM 树。 感受不同!

DOM 树:

<ul>
  <li>
    <a>
      <span></span>
    </a>
  </li>
</ul>

.ul 
.ul > li 
.ul > li > a 
.ul > li > a > span 

BEM-树:

<ul class="menu">
  <li class="menu__item">
    <a class="menu__link">
      <span class="menu__text"></span>
    </a>
  </li>
</ul>

.menu 
.menu__item 
.menu__link 
.menu__text 

参考文献:

“元素是块的组成部分,不能在其外部使用。” https://en.bem.info/methodology/key-concepts/#element

元素是块的一部分!不是元素的一部分! 阅读 BEM-methodology 的作者 Vitaly Harisov:https://twitter.com/harisov/status/403421669974618112

像“block__elem__elem___elem”这样的类名意味着编码人员不了解 BEM 中的任何内容。

另请阅读:

https://en.bem.info/methodology/faq/#why-does-bem-not-recommend-using-elements-within-elements-block__elem1__elem2 http://getbem.com/faq/#css-nested-elements

有一篇关于 Web 会议 WebCamp: Front-end Developers Day 的报告(俄语)关于这个主题:https://www.youtube.com/watch?v=kBgHdSOj33A + 幻灯片:http://ihorzenich.github.io/talks/2015/frontendweekend-bem/

【讨论】:

以上是关于如何使用 BEM 正确设置元素的范围?的主要内容,如果未能解决你的问题,请参考以下文章

如何使BEM减少麻烦

使用 BEM 时命名包装器元素类

SMACSS 和 BEM:如何在模块中定位模块?

将 BEM CSS 与 Angular 指令一起使用

使用 Meteor 时如何正确设置嵌套 #each 空格键迭代器的范围?

我使用的Bem的习惯