Learn and Understand BEM in CSS

What is BEM?

BEM stands for Block, Element, and Modifier. BEM is used to write cleaner CSS code by following naming conventions. You might be thinking "I don't need this! I write perfectly fine CSS without following a convention!" Sure you may be right, but once a project becomes larger, it becomes harder to scale. BEM, one out of the many approaches out there, can solve this issue by structuring your code and maintaining it in a system. Once you follow these rules, you will realize your code is much easier to update and maintain!

You can think of a block as a parent component. For example, a user profile card can be thought of as a block because it contains many child components or elements, such as the user's avatar, username, and bio. An element is a part of the block and has no standalone meaning. Modifiers are used to modify the appearance of a block or element.

In this example, we are going to build a user profile card using BEM. First, let's create a block

1) Block

<style>
    .user {}
</style>

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

Next, we want to add elements. A user profile card contains many elements such as an avatar, the user's name, and bio. So let's add those!

2) Elements within a Block

<style>
    .user {}
    .user__avatar {}
    .user__name {}
    .user__bio {}
</style>

<div class="user">
    <img class="user__avatar" src="images/avatar.jpg" alt="Avatar" />
    <div class="user__name">Jane Doe</div>
    <div class="user__bio">I am a Full Stack Developer and Designer</div>
</div>

As you can see, the naming convention for an element would be the block's name, two underscores, and the name for the element. Since user is our block, an avatar element would be user__avatar. Also, you may have noticed that we directly target the classes without reference to the parent. This is how BEM is more effective and reduces the need for specificity. The reason is because of the way we are naming the elements.

Now, let's say we want to add a button to this user card block. You might be thinking it would make sense to make a new element called "user__btn" and plug it right in. That is still valid BEM, but ask yourself this: Is that button really only going to be used for a user profile card? This button can be used anywhere throughout our website, so it makes more sense for it to be a block element!

3) Block within another Block

<style>
    .user { /* Add your styles here */ }
    .user__avatar { /* Add your styles here */ }
    .user__name { /* Add your styles here */ }
    .user__bio { /* Add your styles here */ }
    .btn { /* Add your styles here */ }
</style>
<div class="user"> 
    <img class="user__avatar" src="images/avatar.jpg" alt="Avatar" />
    <div class="user__name">Jane Doe</div>
    <div class="user__bio">I am a Full Stack Developer and Designer</div> 
    <button class="btn">View</button>
</div>

As you can see, we added a new button block within the user block. This button block can be used anywhere and doesn't have to be inside of the user block.

Now, let's get to modifiers. Once again, a modifier changes the styling of a block or element. Suppose we want to modify the View button, then you must add a modifier class with two dashes after the name of the block or element like so:

4) Modifier on a Block or Element

<style>
...
.btn { /* Add your default button styles here */ }
.btn--primary { /* Add your primary button styles here */ }
</style> 

<button class="btn btn--primary">View</button>

The great thing about this is that you can first set default styles to the button, then add a modifier that slightly alters the default button. The .btn class contains the default styles for your button block, and .btn--primary contains the styles that modify it!

Now, what if we want to add a modifier to the user block entirely? You can, and you can also target child elements by using that modifier like so:

5) Modifier on a Block and targeting its children

<style>
...
.user--dark { background-color: #000; }
.user--dark .user__avatar { /* Add styles here */ }
.user--dark .user__name { /* Add styles here */ }
.user--dark .user__bio { /* Add styles here */ }
.user--dark .btn--primary { /* Add styles here */ }
</style>

<div class="user user--dark">
     <img class="user__avatar" src="images/avatar.jpg" alt="Avatar"/>
     <div class="user__name">Jane Doe</div>
     <div class="user__bio">I am a Full Stack Developer and Designer</div>
     <button class="btn btn--primary">View</button>
</div>

So when you add a modifier to a block, that's how you can target child elements.

And that's BEM for ya folks! 🥳🎉

I hope you guys learned a thing or two from this quick tutorial! Stay tuned for more!