Search code examples
cssbem

BEM naming convention for nested tiny parts


Just started coding with BEM naming methodology. I wondered how to name nested tiny parts.

I attached sample layout below, please take a look.

There are two spans inside h3 and I want them to have different style.

Then shall I just name them like they belong to their parent:

class="en product-lineup__title-en"
class="non-en product-lineup__title-non-en"

or like they belong to their title (but it looks like BEEM...):

class="en product-lineup__title__en"
class="non-en product-lineup__title__non-en"

or just leave it blank then in CSS

.product-lineup__title span:first-child
.product-lineup__title span:nth-child(2)

Which is the best way or do I misunderstand BEM rule in the first place?

enter image description here


Solution

  • BEM is a methodology about reusable blocks. If you see a visual pattern that is repeated in the UI, then you should consider to see it as a block, not an element. Elements are the block details.

    For your wireframe, I suggest two blocks: the lineup block is responsible for the global layout:

    <ul class="lineup">
      <li class="lineup__item"></li>
      <li class="lineup__item"></li>
      …
    </ul>
    

    In each <li>, there is an instance of a product block:

    <article class="product">
      <img class="product__img">
      <h3 class="product__title">…</h3>
      <div class="product__text">…</div>
    </article>
    

    If you want to keep your current HTML structure, then you have a mix on <li> markups:

    <ul class="lineup">
      <li class="lineup__item product">
        <img class="product__img">
        <h3 class="product__title">…</h3>
        <div class="product__text">…</div>
      </li>
      …
    </ul>
    

    Here the lineup__item CSS class is responsible for positioning the child block product in the parent block linup. A block should not position by itself (it wouldn't be reusable).

    Then, your element product__title has two children en and non-en. With BEM, an element cannot be parent of other elements. But it can nest brother elements. You can do:

    <h3 class="product__title">
      <span class="product__title-en"></span>
      <span class="product__title-non-en"></span>
    </h3>
    

    In the BEM tree, title, title-en, title-non-en are all child elements of the product block. It is the light solution.

    But maybe you'll realize that this kind of dual titles is a visual pattern used outside the product block, or maybe just for clarity, you can decide to make a dual-title block for that.

    <h3 class="product__title dual-title">
      <span class="dual-title__en"></span>
      <span class="dual-title__non-en"></span>
    </h3>
    

    Here the CSS class product__title is responsible for positioning the child block dual-title in the parent block product.