BEM – meaning block, element, modifier – is a front-end naming methodology developed by the team at Yandex.
BEM follows simple rules to name and organise your CSS and gives everyone on a project a declarative syntax which they can use so that they're on the same page. BEM is ideal for teams of developers on larger projects.
Introduction
Naming CSS classes is probably the most difficult part of a UI developer’s job. While some developers just like to use simple, identifiable names for their classes, others tend to follow a proper convention for naming their markup.
BEM is amongst the more popular naming conventions which people follow. The reason being its simplicity of approach, and easy adaptability.
But with so many different conventions and everyone following a different approach, how do you know if BEM is right for you?
Well, let's find out!
We’ve had a bunch of discussions surrounding the topic, here on Hashnode :
- How do I organise my CSS?
- Moving existing code to BEM, is it worth it?
- What is the best way to organise your CSS?
- What are the things that you consider while defining the name of a class in CSS? How do you consider it to be the perfect name for that class?
With this guide, we will take a look at how BEM works and find out if it is the right convention for you, or not.
Getting started with BEM
BEM divides the layout into 3 main units: - Block - Element - Modifier
B for BLOCK
The block is your base element. This is the outermost part of your component.
There's no specific syntax to specify a block.
e.g:
.person {}
E for ELEMENT
This is an element of your block. This is a child of your block level element -- something housed inside the element.
An element is indicated by using double underscores after the block name.
e.g:
.person__arm {}
M for MODIFIER
This is a modifier for your block, or an element of the block.
A modifier is an extension which specifies some change in the style of the block or the element it is applied to.
A modifier is indicated by using double dashes after the class name which allows you to overwrite the styles for a specific type of a block, or an element.
e.g:
.person__arm--left {} / .person__arm--right {}
How to BEM?
The Markup
<div class="person">
<div class="person__arm person__arm--left"> ... </div>
<div class="person__arm person__arm--right"> ... </div>
</div>
The Styles
Assuming that you are using some CSS preprocessor, you would write your styles the following way:
.person {
&__arm {
&--left { ... }
&--right { ... }
}
}
The equivalent CSS code output from this would be:
.person { .. }
.person__arm { .. }
.person__arm--left { ... }
.person__arm--right { ... }
All rules in a hierarchy, but the output in the same level... isn't that sweet?
Why to BEM?
Organized naming
Again, for big projects, following an organized naming convention gives everyone on a project a declarative syntax which they can use so that they're on the same page.
Ideally, while reading the markup, you should be able to know if one element depends on an other element, even without looking at its CSS and BEM does exactly that.
eg: person__arm
would be dependent on person
, you can infer that without even knowing what person__arm
does.
With preprocessors, writing CSS is a breeze!
With BEM and preprocessors like LESS and Sass you can write your CSS in a nested manner
So instead of writing individual rules like this:
.parent {
background: red;
}
.parent__child1 {
background: green;
}
.parent__child2 {
background: purple;
}
...you can write rules like:
.parent {
background: red;
&__child1 {
background: green;
}
&__child2 {
background: purple;
}
}
Which is a BIG plus for maintainability.
Avoiding grand-children
Ever got stuck in a situation where you are trying to override some rules but nothing works and you find yourself changing a dozen old rules or worse, you end up using !important
at a few places?
This happens because you have rules going till multiple grand children in your CSS.
Let's all agree that grand children are a big pain. If you're using grand children everywhere, you're doing something wrong. (Did that come out wrong?)
With BEM, when you can avoid using grand children rules and it would still make sense when you're reading the rules.
Code re-use
While making a new style for a component, you can easily see which modifiers and children already exist, and realise if there's a need to write any CSS in the first place because there is a pre-existing modifier that does what we need.
Conclusion
BEM has simple, easy to understand and logical; follows simple rules which would help you name and organize your CSS.
BEM is ideal for teams of developers on larger projects where designers and developers consistently name components for easier communication between the team members.
However, moving legacy code to BEM involves a lot of effort and time investment, especially if the existing code liberally uses complex selectors and class combinations.
With a hierarchy going till grand-grand children in the legacy code, moving to BEM can literally mean writing the code from scratch.
But is BEM worth it?
That's a decision which you'd have to take!