BEM was invented to stop CSS from breaking across 100 services. The industry adopted it to name twelve classes on a landing page.
One does wonder whether anyone read the original brief.
The Original
Yandex, 2005. One hundred services. One hundred and fifty front-end developers.
One global CSS scope. Selectors like .result .albums .info collided
across services because nobody had agreed on naming. The cascade was not the
defect. The absence of a shared vocabulary was.
That was an organisation problem. BEM treated it as a language problem.
No CSS Modules. No Shadow DOM. No @scope. No @layer.
The browser was IE6. A clear nomenclature would have sufficed. Instead, an
entire methodology was constructed to enforce one:
.block__element--modifier. Flatten everything. No cascade,
no collision.
Even at Yandex, this was over-engineered. They got their nomenclature. Along with DOM pollution, unreadable markup, and a war against the very language they were writing in.
The Copy
Smashing Magazine, 2013. CSS-Tricks, 2015. By 2016, BEM was "best practice." The HTTP Archive found BEM patterns on 34% of websites by 2021.
Developers with messy stylesheets saw BEM as discipline. A system that forced structure. What they overlooked: it forced far more complexity than learning to write clean CSS ever would have.
The Missing Context
The gulf between the original and the copy is not a matter of degree. It is a matter of planet.
Yandex.Mail's cascade measurably slowed rendering. Flat selectors were a performance decision. Nobody in 2016 ran those benchmarks. "Best practice" was sufficient motivation, which is rather the problem with best practices in general.
The Cascade
Every methodology has a trajectory. BEM's is particularly instructive because each step defeats the previous one's purpose.
BEM was adopted to escape the cascade. The industry ground it straight back
into one via preprocessors. The moment a team writes &__element
in a Sass file, they are nesting selectors. They are cascading. They have rebuilt
the thing they were avoiding, only now with
eye-gougingly ugly syntax
and a preprocessor dependency.
The Simpler Answer
Nicole Sullivan published OOCSS in 2009. Separate structure from skin. Reuse through composition. No special syntax. No tooling. Just CSS, written with discipline.
OOCSS works with the cascade. BEM works against it. The difference is not stylistic. It is philosophical: one approach trusts the language, the other assumes it is broken.
The Car, Assembled
The car dealership analogy deserves more than a passing mention. Let us build one. First in BEM, then in the CSS that exists today.
The markup, BEM style. Every element encodes its parent in the name. Every variant is a modifier glued to the element it belongs to:
<div class="car car--red-roof--yellow-doors">
<div class="car__engine car__engine--v8">...</div>
<div class="car__transmission car__transmission--manual">...</div>
<div class="car__safety car__safety--airbag">...</div>
</div>
The CSS that goes with it:
.car { display: grid; }
.car--red-roof--yellow-doors { /* this exact combination */ }
.car--red-roof--blue-doors { /* and this one */ }
.car--black-roof--yellow-doors { /* and this one */ }
.car__engine { /* base engine */ }
.car__engine--v8 { /* v8 variant */ }
.car__engine--turbo { /* turbo variant */ }
.car__engine--v8-turbo { /* wait, both? new modifier */ }
.car__transmission { /* base gearbox */ }
.car__transmission--manual { /* manual variant */ }
.car__safety { /* base safety */ }
.car__safety--airbag { /* airbag variant */ }
.car__safety--airbag--abs { /* both? another modifier */ }
Twelve selectors and counting. Flat. No cascade. Every combination of variants requires its own modifier because BEM has no composition model. Red roof with blue doors? New modifier. V8 with turbo? New modifier. The naming committee is in permanent session. This example exaggerates slightly for clarity, but anyone who has inherited a mature BEM codebase knows the truth: production is worse.
Now the same car in modern CSS. The markup first:
<div class="car">
<div class="engine v8">...</div>
<div class="transmission manual">...</div>
<div class="safety airbag">...</div>
<div class="roof red">...</div>
<div class="doors yellow metallic">...</div>
</div>
Reads like a sentence. Now the CSS, with @layer,
native nesting, and @scope:
@layer components {
.car {
display: grid;
.engine { /* base engine layout */ }
.transmission { /* base gearbox */ }
.safety { /* base safety systems */ }
.roof { /* base roof */ }
.doors { /* base doors */ }
}
}
@layer variants {
.v8 { /* v8 power delivery */ }
.manual { /* manual shift pattern */ }
.airbag { /* airbag deployment zones */ }
}
@layer themes {
.red { /* red paint */ }
.yellow { /* yellow paint */ }
.metallic { /* metallic finish */ }
}
@scope (.car) {
:scope { /* scoped to this component */ }
.engine { /* cannot leak outside .car */ }
}
Three layers. Structure in components, options in
variants, paint in themes. The cascade resolves
precedence by layer order, not by selector weight or naming gymnastics.
@scope guarantees .engine inside .car
cannot collide with .engine anywhere else. Native nesting
keeps context visible without flattening it into underscores.
Add a turbo option? One class: .turbo, in the
variants layer. No naming committee. No methodology.
Just CSS, written as CSS.
The Timeline
The history is rather telling. BEM arrived when nothing else existed. Then everything else arrived. BEM stayed.
By 2025, CSS has @scope,
@layer,
:where(),
native nesting,
and Modules.
The scoping problem that BEM was built to work around has been solved natively,
multiple times, by the platform itself.
The Irony
The "C" in CSS stands for Cascading. BEM treats that as a defect. That is not simplification. That is thinking in the wrong direction entirely.
In 2005, it was the only direction available. In 2026, it is a deliberate choice to ignore twenty years of language evolution. The naming convention was copied. The problem it solved was not.
BEM was over-engineered at its origin and bloat everywhere else. The industry copied the complexity and never looked at what was already there.
BEM solved a real problem for 150 engineers sharing one CSS scope across 100 services on IE6. The critique is not the original. It is the copy. If your team has three developers and one project, you do not need a naming convention designed for a Russian search engine's global stylesheet. You need to learn CSS.