Difficulty: Intermediate
What is BEM methodology? Why is it useful for CSS architecture?
BEM stands for Block Element Modifier - a naming convention for CSS classes.
- Block: standalone component (.card, .navbar, .form) - Element: part of a block, no meaning alone (.card__title, .card__image) - Modifier: variation or state (.card--featured, .card__title--large)
Benefits: 1. Low specificity (all single class selectors) 2. Self-documenting (class name tells you the structure) 3. No naming conflicts (block scopes everything) 4. Easy to find in codebase (search for .card__) 5. No nesting needed (flat selectors)
Alternatives: SMACSS, OOCSS, Atomic CSS (Tailwind), CSS Modules, CSS-in-JS.
<!-- Block: standalone component -->
<div class="card">
<!-- Elements: parts of the block -->
<img class="card__image" src="photo.jpg" alt="" />
<div class="card__body">
<h3 class="card__title">Title</h3>
<p class="card__description">Description</p>
<a class="card__link" href="#">Read more</a>
</div>
</div>
<!-- Modifier: variation -->
<div class="card card--featured">
<img class="card__image" />
<h3 class="card__title card__title--large">Featured</h3>
</div>
<!-- Another block -->
<nav class="navbar">
<a class="navbar__logo" href="/">Logo</a>
<ul class="navbar__menu">
<li class="navbar__item navbar__item--active">Home</li>
<li class="navbar__item">About</li>
</ul>
</nav>
Block is the component name. Element uses __ (double underscore). Modifier uses -- (double dash). Never nest elements: card__body__title is wrong.
/* Block */
.card {
background: white;
border-radius: 0.5rem;
box-shadow: 0 1px 3px rgb(0 0 0 / 0.1);
overflow: hidden;
}
/* Elements - flat, not nested */
.card__image {
width: 100%;
height: 200px;
object-fit: cover;
}
.card__body {
padding: 1.5rem;
}
.card__title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
.card__description {
color: #6b7280;
line-height: 1.6;
}
/* Modifiers - extend the base */
.card--featured {
border: 2px solid #3b82f6;
}
.card--horizontal {
display: flex;
}
.card__title--large {
font-size: 1.5rem;
}
/* NO nesting needed! All specificity = (0,1,0) */
Every BEM selector has the same specificity (0,1,0) because they're all single classes. No specificity wars, no nesting, no !important needed.
// Sass makes BEM easier with & parent selector
.card {
background: white;
border-radius: 0.5rem;
&__image {
width: 100%;
object-fit: cover;
}
&__title {
font-size: 1.25rem;
&--large {
font-size: 1.5rem;
}
}
&__body {
padding: 1.5rem;
}
// Modifier
&--featured {
border: 2px solid #3b82f6;
}
&--horizontal {
display: flex;
// Modify element within modifier context
.card__image {
width: 200px;
height: auto;
}
}
}
// Compiles to flat CSS:
// .card { }
// .card__image { }
// .card__title { }
// .card--featured { }
Sass & nesting generates flat BEM selectors. The source is organized hierarchically but the output is flat single-class selectors.
BEM, CSS Architecture, Naming Conventions, Maintainability, Scalability