BEM Methodology

Difficulty: Intermediate

Question

What is BEM methodology? Why is it useful for CSS architecture?

Answer

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.

Code examples

BEM Naming Convention

<!-- 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.

BEM CSS Rules

/* 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.

BEM with Sass/SCSS

// 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.

Key points

Concepts covered

BEM, CSS Architecture, Naming Conventions, Maintainability, Scalability