跪拜 Guibai
← Back to the summary

BEM Class Names Give Front-End CSS a Naming Contract That Ends Selector Fights

BEM International Naming Conventions in Front-End Development: Stop CSS From Fighting

Start with a “disaster case”

Have you ever been in this situation:

You write a .btn style for a button and feel great. The next day, a colleague writes a .btn in their own module with totally different styles. The two .btn classes meet on the page, CSS cascade rules start “fighting,” and the button ends up looking like a mess. The two of you stare at the screen, dumbfounded: whose fault is this, anyway?

This is the classic scene caused by CSS naming chaos. And BEM is the “peace treaty” that ends it.


What is BEM?

BEM is the abbreviation for Block, Element, and Modifier. It was proposed by the Russian company Yandex and is a CSS class-naming methodology.

Its core idea is simple: break the page into independent component blocks, and use one unified naming rule so every class name announces what it is.


Three roles, each doing its job

🧱 Block — an independent component

A Block is an independent, reusable component on the page. It does not depend on anything else and works fine on its own.

.header { }
.menu { }
.button { }
.card { }

Analogy: A Block is like a “wheel” in a set of LEGO bricks. It is complete by itself and does not need to attach to anything.

👶 Element — a part of a Block

An Element is a child part of a Block. Outside the Block it has no meaning. Use double underscores __ to connect the Block and the Element.

.menu__item { }
.card__title { }
.button__icon { }
.search-form__input { }

Analogy: menu__item is “one item in the menu.” It was born to belong to menu; take it out alone and no one knows what it is for.

🎨 Modifier — a state or variant

A Modifier describes a Block or Element's different state, appearance, or variant. Use double hyphens -- when naming it.

.button--primary { }
.button--disabled { }
.menu__item--active { }
.card--dark { }

Analogy: button--disabled is “the disabled button.” It is still a button, just in a different state.


The complete formula at a glance

.block { }
.block__element { }
.block--modifier { }
.block__element--modifier { }

Remember this formula and you can go anywhere without fear.


Hands-on practice: a card component

Here is a complete example:

<div class="card card--featured">
  <h2 class="card__title">Featured Product</h2>
  <p class="card__description">This is a product description.</p>
  <button class="card__button card__button--primary">Buy Now</button>
</div>
/* Block */
.card {
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

/* Block Modifier */
.card--featured {
  border-color: #ff6b6b;
  box-shadow: 0 4px 12px rgba(255, 107, 107, 0.2);
}

/* Elements */
.card__title {
  font-size: 18px;
  margin-bottom: 8px;
}

.card__description {
  font-size: 14px;
  color: #666;
}

.card__button {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

/* Element Modifier */
.card__button--primary {
  background-color: #ff6b6b;
  color: white;
}

See, just by looking at the class names you already know:

Class names speak for themselves. No comments needed.


Why is BEM so good?

Advantage Description
Avoids style conflicts Every class name has a unique “identity,” so they don't overwrite each other
Self-documenting The class name reveals structure and relationships; newcomers get it immediately
Highly reusable Blocks exist independently; you can drag them into any page
Team-friendly Unified rules mean nobody has to guess someone else's naming habits
Low specificity All single-level class selectors, no deep nesting; better performance and easier to override

Some best practices

  1. All lowercase with hyphens between words: search-form ✅, searchForm ❌
  2. No nested element names: don't write card__body__text; just use card__text
  3. Modifiers can't be used alone: card--dark must appear together with card in the HTML
  4. Avoid deep CSS nesting: BEM encourages targeting with class names instead of selectors like .card .body .text
  5. Preprocessors make it more comfortable: with Sass's & you can write a lot fewer repeated prefixes
.card {
  padding: 20px;

  &__title {
    font-size: 18px;
  }

  &__button {
    padding: 8px 16px;

    &--primary {
      background: #ff6b6b;
    }
  }
}

BEM's “small downsides”

Of course, BEM is not perfect:

But overall, in team collaboration and medium-to-large projects, the sense of order BEM brings far outweighs its “typing cost.”


Final words

BEM is essentially a convention. It doesn't force you to do anything; it just tells you: if everyone follows the same naming rules, the CSS world will be much more peaceful.

Next time you are about to write a .btn, think about it: which Block does it belong to? Does it have a special Modifier? Once you answer those, your CSS code will go from “a pile of loose sand” to “a well-trained army.”

Naming is one of the two hardest things in programming, and BEM at least solves half of it. 😉