Search code examples
htmlcssbem

What is considered to be "independent" in BEM?


Sometime ago I got interested in BEM methodology and tried to use it in my projects. I probably used some modified version of it, so my css looks like this:

.block for blocks

.block__element for elements

.block--modifier and .block__element--modifier for block and element modifiers.

I do not use elements within elements, so I have .block__element-two instead of .block__element-one__element-two.

It all seems pretty convenient, but I still don't get some key principles of it. For example, what should be considered as "independent entity"?

Let's say we have three different blocks with headers, with the headers keeping the same set of rules. As we use these headers all around the page, and probably on some other pages, they seem to be independent. So we can create a block for them and use it every time. And in this case we write the rules only once.

Demo for header as a block:

http://plnkr.co/edit/rCWCk3yGJJzAWpHqzpHa?p=preview

<div class="up-content">
  <h4 class="header">upper</h4>
  <div class="up-content__picture">picture</div>
  <div class="up-content__picture">picture2</div>
  <div class="up-content__picture">picture3</div>
</div>
<div class="mid-content">
  <h4 class="header">middle</h4>
  <div class="mid-content__text">Lorem ipsum dolor sit amet.</div>
  <div class="mid-content__images">
    <div class="mid-content__graphic">graphic one</div>
    <div class="mid-content__graphic">graphic two</div>
  </div>
</div>
<div class="bottom-content">
  <h4 class="header">bottom</h4>
  <div class="bottom-content__video">YOUTUBE VIDEO</div>
</div>

.header{
 color:red;
 margin-bottom:10px;
 font-size:18px;
 text-decoration:underline;
 text-transform:uppercase;
 }

But at the same time we see that all the headers are children of some parent blocks, so they depend on them. Then we can consider them as elements and therefore give them separate names. In this case we will have to duplicate the same css for three times.

Demo for headers as elements:

http://plnkr.co/edit/nxh0ObqXDSRKg3N4zAKc?p=preview

<div class="up-content">
  <h4 class="up-content__header">upper</h4>
  <div class="up-content__picture">picture</div>
  <div class="up-content__picture">picture2</div>
  <div class="up-content__picture">picture3</div>
</div>
<div class="mid-content">
  <h4 class="mid-content__header">middle</h4>
  <div class="mid-content__text">Lorem ipsum dolor sit amet.</div>
  <div class="mid-content__images">
    <div class="mid-content__graphic">graphic one</div>
    <div class="mid-content__graphic">graphic two</div>
  </div>
</div>
<div class="bottom-content">
  <h4 class="bottom-content__header">bottom</h4>
  <div class="bottom-content__video">YOUTUBE VIDEO</div>
</div>

.up-content__header{
 color:red;
 margin-bottom:10px;
 font-size:18px;
 text-decoration:underline;
 text-transform:uppercase;
 }

.mid-content__header{
 color:red;
 margin-bottom:10px;
 font-size:18px;
 text-decoration:underline;
 text-transform:uppercase;
 }

.bottom-content__header{
 color:red;
 margin-bottom:10px;
 font-size:18px;
 text-decoration:underline;
 text-transform:uppercase;
 }

So what approach should I choose? Is there any way to clearly identify things as independent blocks or dependent elements?

UPD Today I asked similar question on the BEM forum and learned about mixes.

https://en.bem.info/method/definitions/#mix

In BEM, mix is used when you need to blend two entities together. As I understand, it means that the same thing can be a block and an element simultaneously. So, in my case, we can combine an element with a block, an it will look like this:

http://plnkr.co/edit/2VoROHHULVATpyejJmRn?p=preview

<div class="up-content">
  <h4 class="up-content__header header">upper</h4>
  <div class="up-content__picture">picture</div>
  <div class="up-content__picture">picture2</div>
  <div class="up-content__picture">picture3</div>
</div>
<div class="mid-content">
  <h4 class="mid-content__header header">middle</h4>
  <div class="mid-content__text">Lorem ipsum dolor sit amet.</div>
  <div class="mid-content__images">
    <div class="mid-content__graphic">graphic one</div>
    <div class="mid-content__graphic">graphic two</div>
  </div>
</div>
<div class="bottom-content">
  <h4 class="bottom-content__header header">bottom</h4>
  <div class="bottom-content__video">YOUTUBE VIDEO</div>
</div>

.header{
 color:red;
 margin-bottom:10px;
 font-size:18px;
 text-decoration:underline;
 text-transform:uppercase;
 }

Formally all the headers remain elements, but all their css rules are set in the .header block. We mix the entities together.

It probably means that header element classes in html will remain useless, as we have the .header block for all the rules we need. I don't know, if it's a normal practice, but anyway, mixes make it all much easier.


Solution

  • You already have a hint in the naming of your content blocks: up-content, mid-content and bottom-content all have content in their names, so they should be considered different versions of content:

    .content{}
    .content--up{}
    .content--mid{}
    .content--bottom{}
    

    Now all of these content versions share an element, header, which can therefore be defined as an element of the basic content block:

    .content__header{}
    

    This allows a single definition of the header, making it available in all of your content versions:

    <div class="content content--up">
        <div class="content__header"></div>
    </div>
    
    <div class="content content--mit">
        <div class="content__header"></div>
    </div>
    
    <div class="content content--bottom">
        <div class="content__header"></div>
    </div>
    

    See the updated plunkr: http://plnkr.co/edit/bl4LKSIJWifrQxIOCZKZ?p=preview

    You should always be aware of the following though, as someone else already stated in an answer:

    There are a number of variants on how to write BEM classes, so be aware that there is no true standard. It's really more of a set of loose guidelines.