BEM: the methodology that brings order to the chaos of your CSS classes
A practical introduction to BEM (Block, Element, Modifier), the CSS naming convention developed by Yandex. The article explains the logic behind the system, shows its syntax with real examples, and argues why adopting a naming convention has a direct impact on the maintainability and scalability of frontend projects.
- BEM
- CSS
BEM: the methodology that brings order to the chaos of your CSS classes
If you have ever opened someone else’s project (or your own from six months ago) and found classes like .header-title-blue-left-new2, you know exactly the problem BEM addresses.
BEM stands for Block, Element, Modifier — a CSS naming convention developed by the Yandex team that, since its publication, has become one of the most widely adopted standards in frontend development. It is not a framework or a library: it is simply a way of naming things.
The core idea: everything is a block
BEM starts from a simple premise: the interface can be divided into independent, reusable blocks. Each block can contain elements (the parts that make it up) and can have modifiers (variations in appearance or behavior).
The resulting syntax follows this pattern:
.block {}
.block__element {}
.block--modifier {}
.block__element--modifier {}
Two underscores (__) separate the block from the element. Two hyphens (--) introduce a modifier. It is hard to forget once you see it in context.
Blocks, elements, and modifiers in practice
Block
A block is any UI component that makes sense on its own: a navigation menu, a card, a form, a button.
<nav class="nav">...</nav>
<article class="card">...</article>
<button class="btn">Submit</button>
The golden rule: a block does not depend on context. Its style should not change depending on where it is placed on the page.
Element
An element is a part of a block that does not make sense outside of it. The logo inside a header, the title inside a card, the icon inside a button.
<article class="card">
<img class="card__image" src="..." alt="..." />
<div class="card__body">
<h2 class="card__title">Article title</h2>
<p class="card__description">Brief description.</p>
</div>
</article>
Important note: elements are not nested in the naming. Even though card__description is inside card__body in the HTML, the class is written as card__description, not card__body__description. BEM reflects logical structure, not the DOM tree.
Modifier
A modifier expresses a variation of the block or element: active state, alternative size, color theme.
<button class="btn btn--primary">Confirm</button>
<button class="btn btn--secondary btn--large">Cancel</button>
<article class="card card--featured">...</article>
The modifier is always added alongside the base class, not instead of it. btn--primary only makes sense together with btn.
Why BEM works
1. Predictable specificity
With BEM you almost never need more than one class per selector. That means the specificity of your CSS rules is uniform and style conflicts become rare. Gone are the days of desperate !important.
/* ✗ Without BEM: you need context to avoid collisions */
.sidebar .btn { ... }
.header .btn { ... }
/* ✓ With BEM: the name says it all */
.sidebar__btn { ... }
.header__btn { ... }
2. Self-explanatory without documentation
When you see .form__submit--disabled in the HTML, you immediately understand that it is a form’s submit button in a disabled state. There is no need to search through CSS files to understand the relationship.
3. Real reusability
Because blocks do not depend on their context, you can move a card from the homepage to the search results page without touching a single line of CSS.
4. Cleaner collaboration
On large teams, BEM prevents class name collisions. If two people work on different modules and follow the convention, their styles will not step on each other.
When BEM may not be enough
BEM solves component-level organization very well, but it does not dictate how to organize files or how to manage global styles (typography, colors, spacing). That is why it is often combined with folder architecture methodologies like ITCSS or design systems that provide the variables and tokens blocks consume.
It can also feel verbose for small projects or quick prototypes. In those cases, the overhead of thinking in blocks and modifiers may feel unnecessary. BEM shines in medium and large projects, especially on teams.
Common mistakes when starting out
- Nesting element names:
card__body__titleinstead ofcard__title. Avoid it; reflect logic, not the DOM. - Using modifiers without the base class:
<div class="btn--primary">withoutbtn. The modifier is an addition, not a replacement. - Creating blocks for everything: a decorative
<span>inside a component does not need to be a block. If it does not make sense on its own, it is an element.
Conclusion
BEM is not magic, and it does not pretend to be. It is simply an agreement: a common way of talking about interface components through code. That consistency, multiplied by team size and months of project life, ends up being the greatest asset a convention of this kind can offer.
If you do not use it yet, the investment of learning it in an afternoon will pay you back in hours of CSS debugging and misunderstandings in code reviews for years to come.