What is BEM?
Block Element Modifier is not a framework, it is a methodology. It was originally introduced by Yandex. The Core of this methodology is a simple naming convention - the structure of the page is divided into three types of building blocks - blocks, elements and modifiers. These days people usually use just the HTML/CSS naming convention, but originally the methodology was much broader. It covers Javascript, project file structure and generation of HTML from BEM tree templates. This article focuses just on the HTML/CSS part.
Block
A Block represents a standalone reusable entity, which usually contains other blocks and/or elements.
Element
An Element is not a standalone entity and can be used only inside of a block. It is tied to its parent block and has no meaning on its own.
Modifier
A Modifier is a flag, which is used on blocks and elements. It represents a state or variation of blocks and elements. With a modifier you can for example mark that element is disabled, smaller or larger than usual, selected, hovered etc.
Example
In the image above, blocks are marked by green, elements by red and modifiers by blue. You can see that elements are only inside blocks, not standalone. Both main navigation items and follow buttons make sense only within their respective blocks. Blocks, such as links, can be used on their own. You can see, that blocks can be nested - "post-preview" block contains several "link" blocks. Both of these block types can be used on their own. Modifiers add additional variants such as that some links are bigger (preview post heading), navigation item of current section is highlighted or social follow buttons are blue on mouse over.
Naming
All the HTML elements are marked just by class. In CSS, you can reference just class, no HTML tags, no IDs.
Blocks are named as usual by CSS class. For example - main-navigation
.
Element's class also contains the name of the block. Block name is first, then two underscores __
and then element's name. For example main-navigation__navigation-item
.
The Modifier is appended to the block's or element's name with two hyphens --
. For example main-navigation__navigation-item--active
or link--large
.
Note that there is no nesting. Every item contains all the necessary information - that is - element in its class name contains its parent block's name and even the modifier.
Advantages
Performance
When using BEM, all the CSS selector are flat. There are no descendant selectors (such as .header .nav .nav-item
), which are way more expensive to calculate. Because of that, the page should be rendered as fast as possible.
Readability
When examining an element or a block, you get all the required information directly from the HTML element. You can immediately tell to which block the element belongs and which modifier it has. And you can immediately search for corresponding CSS block related to it. You don't need to investigate whether this element behaves differently based on the context in which it is present. No need to check the whole cascade for hidden dependencies.
Selector Specificity
Because all the CSS selectors are flat and only .class
selector is used, everything is kept simple and there is no need to struggle with selector specificity issues.
Flexibility
Because each block is completely independent, you can move them around without worrying that something would break up - e.g. styles getting screwed because the rule was taking into account moved block's parent or a specific position in the DOM.
Furthermore, you can safely duplicate a block, which was originally intended to be "singleton". BEM uses only classes, so you don't need to worry about any selector pointing to ID or that you will suddenly have multiple occurrences of the same ID on the page.
Because BEM uses only classes and does not allow any selectors tied to specific HTML tags (anchors, tables, ...), you can safely change tags without breaking anything. This gives you much more flexibility and freedom for refactoring. What's more, it gives you the confidence to refactor. Without it, large applications with a lot of CSS tend to rot, because you can't be really sure that you will not break something with your changes without even noticing it.
Unified naming
There is a methodology for the unified naming of blocks, elements and modifiers. It makes the communication among the team members much easier. With unique identifiers, you can point to specific parts of the page in a much simpler manner without ambiguity.
Simplicity
While there are other approaches to HTML/CSS naming conventions and methodologies, this one is very simple. There are just three types of entities with a few simple rules and simple, unambiguous naming (block, element, modifier), which makes the terminology immediately obvious. It is very easy to learn and adopt this methodology, unlike some others.
BEM + SASS
Using SASS CSS Preprocessor, you can achieve logical nesting of blocks and elements in you SCSS files, while generated output will be still flat. You can use the &
feature, which represents parent CSS selector when nesting.
.block {
//Block specific CSS here
&__element {
//Element specific CSS here
&--modifier {
// Element with modifier specific CSS here
}
}
}
While this approach helps you to have better-structured CSS code, it has some disadvantages too. You cannot simply search your project for CSS class of an element or nested block, because it is constructed when compiling and is not present in your source SCSS in the same form as it is in your HTML. This makes navigating to corresponding SASS code harder, not to mention automatic renaming by your IDE when refactoring class names.
Alternatively, you can check BEM-SASS library, which provides some mixins to make SASS integration easier.
Alternatives
BEM is not the only CSS methodology out there. Examples of some other very popular ones are Scalable and Modular Architecture for CSS (SMACSS) or Object Oriented CSS.