Skip to content
⚠️ This article was written in 2019. Some content may be outdated.

CSS BEM Naming Convention in Practice

While rolling out the BEM naming convention across our team, we ran into quite a few pitfalls. Here are some lessons we learned that I hope will be useful.

Core Principles ​

BEM stands for Block, Element, Modifier. The naming format is:

css
/* Block: a standalone, meaningful component */
.card {
}

/* Element: a part of a block (double underscore) */
.card__title {
}
.card__body {
}
.card__footer {
}

/* Modifier: a variant or state (double hyphen) */
.card--featured {
}
.card--disabled {
}
.card__title--large {
}

Practical Example ​

html
<div class="card card--featured">
  <div class="card__header">
    <h2 class="card__title card__title--large">Article Title</h2>
  </div>
  <div class="card__body">
    <p class="card__text">Content here...</p>
  </div>
  <div class="card__footer">
    <button class="card__btn card__btn--primary">Read More</button>
  </div>
</div>
css
.card {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}
.card--featured {
  border-color: #409eff;
}
.card__title {
  font-size: 18px;
  margin: 0;
}
.card__title--large {
  font-size: 24px;
}
.card__btn {
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
}
.card__btn--primary {
  background: #409eff;
  color: #fff;
  border: none;
}

Pitfalls to Avoid ​

  1. Don't nest BEM: .card__header__title is wrong — use .card__header-title instead
  2. Modifiers don't stand alone: always include the base class: class="card__btn card__btn--primary"
  3. Block boundaries: child elements belong to the block, not nested elements' blocks

BEM significantly improves CSS maintainability in large projects by eliminating specificity conflicts and making the relationship between HTML and CSS immediately clear.

MIT Licensed