Am I allowed to use element from a parent block, inside a children block?

234 Views Asked by At

I would like to know if, according to BEM methodology, I can have the following structure:

.block1
  .block1__element1
    .block2
       .block1__element2 <-- ??

Am I allowed to use an element from a parent block, inside a children block?

Thanks.

UPDATE:

This is the actual DOM structure:

<div class="head">
  <div class="head__user"></div>
  <div class="head__nav">
    <div class="menu">
       // <-- ???
    </div>
  </div>
</div>

According to best practices of BEM methodology: am I allowed to move the element with head__user inside the menu block? Or all elements inside the menu block need to start with the menu__ prefix?

I hope this clears out the problem.

3

There are 3 best solutions below

0
On BEST ANSWER

I think this variant is allowed:

<div class="head">
  <div class="head__nav">
    <div class="menu">
       <div class="head__user"></div>
    </div>
  </div>
</div>

I haven't found the current part in the official BEM documentation, but I've found this part:

The block name defines the namespace, which guarantees that the elements are dependent on the block (block__elem).

A block can have a nested structure of elements in the DOM tree:

Example

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

However, this block structure is always represented as a flat list of elements in the BEM methodology:

Example

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

This allows you to change a block's DOM structure without making changes in the code for each separate element:

Example

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

The block's structure changes, but the rules for the elements and their names remain the same.

I understand it as there is only one rule about HTML structure for elements in BEM: an element has to be inside its block (it doesn't matter how deep).

One possible problem that I can imagine for this case is using some of BEM tree formats. But if you don't need it, I think there's no problem.

6
On

I been using BEM for sometime and from what I got it's not recommended nor intended to be used like that. You can nest different BEM elements to each other like menu-blockintohead-block, but menu-block items should not go outside its parent menu-block, like you should not put menu-block__item at the top of head-block. Does it makes sense? :)

To illustrate there are two ways to go. What should be noted here is that depending on the scale of your project and how you build things (component based?). If you don't have a large project and are not doing or reusing the menu else where you can do it both ways. Lets say your menu is huge amount of html/css I would do it like #1

This is not correct

<div class="head">
  <div class="head__user"></div>
  <div class="head__nav">

    <div class="menu">
       <div class="head__something"></div>
    </div>

  </div>
</div>

Recommended solution
Based on this part of the documentation. Now you can chop your own header design into blocks, does this below match?

<div class="head">
  <div class="head__user"></div>
  <div class="head__nav">
    <div class="menu">
       <div class="menu__something"><img src="" class="menu__image" /></div>
    </div>
  </div>
</div>
0
On

I would consider making the potential head__something into simply something, and then to provide multiple modifications of it. e.g. something--head and something--menu.

<div class="head">
  <div class="head__user"></div>
  <div class="head__nav">
    <div class="menu">
     <div class="something--menu" />
    </div>
  </div>
  <div class="something--head" />
</div>

Also, refactoring further, I would consider getting rid of head__nav as it probably does not add any richer semantics than menu.

<div class="head">
  <div class="head__user"></div>
  <div class="menu">
    <div class="something--menu" />
  </div>
  <div class="something--head">for those cases where you want <code>something</code> directly descending from <code>head</code></div>
</div>