Block, Element, Modifier - BEM Naming Convention in CSS


In this video you will learn what are block, element, modifier in BEM. They are 3 main pillars of BEM naming convention in CSS. If you ever had problems with global styles in CSS then BEM is the solution to your problems.

Introduction

Hi I'm Oleksandr Kocherhin from monsterlessons-academy, where I'm teaching you how to become a developer or improve your skills of being a developer in learning by doing way. And if you are new here don't forget to subscribe and I will link everything that I'm mentioning in the description.

So let's get started.

Content

So what problem do we have? All our css in frontend is global. Which means we can't just create 2 different css files and put there the same class. Because all styles are registered as global and that's it.

Nowadays we have frontend frameworks for single page applications like react, angular and vue and they are have a solution to this problem inside. So they all are build with components pattern and when you create styles inside them they prefix them unique with class or attribute and you can out of the box so called "scoped css". So your styles are completely isolated inside component.

But the whole web is not only frontend frameworks there are millions of projects where html is still rendered on backend, or they don't want to use heavy soluctions for this and they also need to solve global styles problems.

This is where BEM comes in. It's a methodology and not a framework or library. This means that you don't need to install anything additionaly, you can just continue to write plain css but in other way and you would never have global styles problem.

For this we need to change our mindset a little big. We need to think about css not like just a bunch of classes to style something but like a components or entities to build our project. Then we plan our every component as isolated and fully function part of the application that we can reuse.

Let's check on the example. So we need a use a user card. It's an isolated component that we will reuse all over again. The idea of BEM that our component that we build is a block. Then inside we can have elements. So here is markup for our user card.

<div class="user-card">
</div>

So this is what we call a block. It's just some unique across our styles name. Now we want to put inside an image of the user.

<div class="user-card">
  <img class="user-card__image" src="https://via.placeholder.com/350x350"/>
</div>

So here is image inside and we have a strange class here. As you can see it looks exactly like previous class then two underscore symbols and the name. This is what we are calling element. It's a child of the block. All children are written with block prefix and two underscore symbols.

Now let's add some content after the image.

<div class="user-card">
  <img class="user-card__image" src="https://via.placeholder.com/350x350" />
  <div class="user-card__content">
    <div class="user-card__header">Kristy</div>
    <div class="user-card__date">Joined in 2013</div>
    <div class="user-card__description">
      Kristy is an art director living in New York
    </div>
  </div>
  <div class="user-card__footer">
    22 Friends
  </div>
</div>

As you can see we give every element that we plan to style later a class with our block prefix. So here just some plain markup for us. Now all our classes are unique and the only way of breaking them is if we create the block with the same name. Which should be fine because now we don't have just a bunch of classes but blocks where we organize css inside.

Now let's add some styles

  .user-card {
      width: 290px;
      background: #fff;
      border-radius: 4px;
      box-shadow: 0 1px 3px 0 #d4d4d5, 0 0 0 1px #d4d4d5;
      font-size: 14px;
  }

  .user-card__image {
      width: 100%;
  }

  .user-card__content {
    padding: 14px;
  }

  .user-card__header {
    font-weight: 700;
    font-size: 18px;
  }

  .user-card__date {
    color: rgba(0,0,0,.4);
  }

  .user-card__description {
    margin-top: 7px;
  }

  .user-card__footer {
    padding: 14px 10px;
    border-top: 1px solid rgba(0,0,0,.05);
    color: rgba(0,0,0,.4);
  }

As you can see everything is looking already good enough. Here are some important things here. All your css classes are first of all isolated and secondly each class belongs directly to our block. So they can be all global and there won't be any name collisions.

As you can see all our code is flat. We don't have nesting, we don't write styles with several selectors. And it's super important. We don't write styles which depend on several elements.

The first mistake that people are making is that are trying to nest elements. For example we could say that user-card__header belongs to content and not directly to our block. So people start to write

.user-card__content__header {
}

This is a bad idea. In perfect world we want to have all elements that we can't render inside block on their own even if we remove all other elements. Of course it's not always possible but we need to try and do it like that. Than we can remove part of elements when we reuse our block.

<div class="user-card">
  <img class="user-card__image" src="kristy.png" />
  <div class="user-card__content">
    <div class="user-card__header">Kristy</div>
  </div>
</div>

Now you know what is block and element. The last thing in BEM is modifier. It is need to have different states of our block or element. Let's make our user-card disabled.

<div class="user-card user-card--disabled">
</div>
.user-card--disabled .user-card__image {
  opacity:0.5;
}

As you can see we added a modifier to our block. When we wrote a styles that we want to change our element image when this modifier is there. So we write element with 2 underscores and modifier with 2 dashes. It is allowed to have modifiers not only on block but on elements also. But I first that my code is cleaner when I have all modifiers in block if it's possible.

But what really simplifies our code in writing BEM is using any preprocessor. I won't install it now and setup but just show you what we can write for example in sass preprocessor and get the same code like we already wrote.

Here am I in sassmeister.com. I just googled sass to css online and this was the first website.

.user-card {
  width: 290px;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 3px 0 #d4d4d5, 0 0 0 1px #d4d4d5;
  font-size: 14px;

  &--disabled {
    .user-card__image {
      opacity:0.5;
    }
  }

  &__image {
    width: 100%;
  }

  &__content {
    padding: 14px;
  }

  &__header {
    font-weight: 700;
    font-size: 18px;
  }

  &__date {
    color: rgba(0,0,0,.4);
  }

  &__description {
    margin-top: 7px;
  }

  &__footer {
    padding: 14px 10px;
    border-top: 1px solid rgba(0,0,0,.05);
    color: rgba(0,0,0,.4);
  }
}

So in sass we can use & which is the same as writing parent. It helps us to write all our children and makes our code less verbose. Also we can now should all our children that we need to change in modifier easier.

Call to action

As you can see with BEM our css is better planned, easier to read and understand have it's more difficult to make an error. And I'm still using it in 2020 in the projects where I don't have isolated styles and I don't want to install hundred of tools if I can do it really easy with BEM. Also keep in mind that there are some other methodologies like Semantic css, smacss which are all solving css global styles problems but differently.

Also don't forget to check my full courses regarding different web technologies. I will link them down in the description box below.

If you find this video helpful, don't forget to subscribe to this channel and hit subscribe button. And I see you in my next video.

🚨 Important

📚 References