Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly set an element's scope using BEM?

Given the following BEM tree structure, where five nested levels exist:

collection-main__features-top__story__byline__author

according to BEM's naming convention, where an element is part of a block and has no meaning outside of the block it belongs to, what is the proper way to name the author class?

Since an author is semantically tied to the byline and the story context, but meaningless under the features-top and collection-main blocks, what is the best BEM name?

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

What happens if a new features block gets introduced?

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

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

Finally, what happens if another collection block gets added and we want to style the second author element in the list?

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

Would we do something like this?

story--collection-main--features-bottom__author

There must be a better option.

like image 588
Eric Xu Avatar asked Jan 12 '15 02:01

Eric Xu


People also ask

How do you use the BEM method?

BEM names intentionally use double underscores and double hyphens instead of single to separate Block-Element-Modifier. The reason is so that single hyphens can be used as word separators. Class names should be very readable, so abbreviation isn't always desirable unless the abbreviations are universally recognizable.

What is BEM pattern?

What is BEM? BEM is a front-end naming method for organizing and naming CSS classes. The Block, Element, Modifier methodology is a popular naming convention for class names in HTML and CSS. It helps to write clean CSS by following some simple rules.

What is the BEM naming convention?

BEM stands for block, element, and modifier. It's a naming convention that divides the user interface into small, reusable components that will prepare us for the changes in design of our websites. This convention also enhances the cross-site copy/paste feature by helping make elements reusable components.


1 Answers

BEM prohibits put an elements in the elements in CSS!
You make the most typical error in BEM markup - writing a block__element__element. You must create new blocks, rather than copying DOM-tree.

For example:
Right HTML:

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

Right CSS:

.block {}
.block__elem1 {}
.block__elem2 {}
.block__elem3 {}

If you need to make an element of an element, then you need to make a new block or make your bem-tree with a single nested elements!

WRONG:

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

RIGHT #1: Make a new block

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

RIGHT #2: Make your bem-tree with a single nested elements

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

Pay attention - you can not put elements in a elements in the css, but you can and should put elements in a elements into html! DOM-tree and BEM-tree can be different.

Do not write strange names, putting the element name in the name of the block!

WRONG:

.block {}
.block-elem1 {}
.block-elem1__elem2 {}

Because you get a problem with odd names when you try to move the block:

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

Nested html-elements is a DOM-tree.
The names of the classes you write is a BEM-tree.
Feel the difference!

DOM-tree:

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

.ul {}
.ul > li {}
.ul > li > a {}
.ul > li > a > span {}

BEM-tree:

<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 {}

References:

"An element is a constituent part of a block that can't be used outside of it." https://en.bem.info/methodology/key-concepts/#element

An element is a part of a block! Not part of element! Read Vitaly Harisov, the author of BEM-methodology: https://twitter.com/harisov/status/403421669974618112

Classname like "block__elem__elem___elem" means that coder didn't understand anything in BEM.

Read also:

  • 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

There is a report (in Russian) on a web conference WebCamp: Front-end Developers Day about this topic: https://www.youtube.com/watch?v=kBgHdSOj33A + slides: http://ihorzenich.github.io/talks/2015/frontendweekend-bem/

like image 150
Ihor Zenich Avatar answered Sep 29 '22 19:09

Ihor Zenich