What Is BEM in CSS: A Practical Naming Convention Guide With Examples

If you have ever opened a stylesheet and found classes like .btn, .btn2, .button-red, .red-button-big all doing similar things, you already know why developers need a naming convention. BEM is one of the most popular answers to that mess, and it has survived every front-end trend since 2010.

In this guide, we will break down what BEM in CSS really means, show you a real component built two ways (messy vs BEM), and help you decide if it still belongs in your 2026 workflow.

What Is BEM in CSS?

BEM stands for Block, Element, Modifier. It is a naming convention (and a methodology) for writing CSS class names so that your styles stay predictable, reusable and easy to maintain, even as a project grows to thousands of lines.

The idea, originally created by the Yandex team, is simple: every class name should tell you exactly what it is and what it does, just by reading it.

The three building parts of BEM

  • Block: a standalone, reusable component. Example: card, menu, search-form.
  • Element: a part of a block that has no meaning on its own. Written with two underscores: card__title, menu__item.
  • Modifier: a flag that changes the appearance or state of a block or element. Written with two dashes: card--featured, menu__item--active.

The full syntax looks like this:

.block {}
.block__element {}
.block--modifier {}
.block__element--modifier {}
css code laptop

Messy CSS vs BEM: A Real Component Comparison

Let’s build the same card component twice. First, the way many beginners write it.

The messy version

<div class="card big featured">
  <img class="image" src="...">
  <h2 class="title red">Hello</h2>
  <p class="text">Some description</p>
  <a class="btn btn-red big-btn">Buy</a>
</div>

What’s wrong here?

  • Generic names like .image, .title, .text will collide with other components.
  • Visual names like .red or .big-btn lie the moment design changes.
  • You cannot tell which class belongs to which component just by reading the HTML.
  • Specificity wars are guaranteed in 3 months.

The BEM version

<div class="card card--featured">
  <img class="card__image" src="...">
  <h2 class="card__title">Hello</h2>
  <p class="card__text">Some description</p>
  <a class="card__button card__button--primary">Buy</a>
</div>

And the matching CSS:

.card { padding: 1rem; border-radius: 8px; }
.card--featured { border: 2px solid gold; }

.card__image { width: 100%; display: block; }
.card__title { font-size: 1.25rem; }
.card__text  { color: #555; }

.card__button { padding: .5rem 1rem; }
.card__button--primary { background: #0066ff; color: #fff; }

Now every class is self-explanatory, scoped to the card component, and impossible to confuse with another part of the site.

BEM Syntax Cheat Sheet

Part Separator Example Meaning
Block (none) search-form Standalone component
Element __ (two underscores) search-form__input Part of a block
Modifier — (two dashes) search-form--dark Variant or state
Element + Modifier both search-form__button--disabled Variant of an element
css code laptop

Why BEM Still Matters in 2026

With Tailwind, CSS Modules, and Vanilla Extract being everywhere, some developers ask if BEM is outdated. The honest answer: it depends on your stack, but BEM still solves real problems.

  1. Zero tooling required. BEM works in any project, even a plain HTML file. No build step, no framework lock-in.
  2. Self-documenting HTML. Anyone reading the markup understands the structure instantly.
  3. Flat specificity. Every selector is a single class, so overrides are predictable.
  4. Team friendly. Large teams stop arguing about naming because the rules are explicit.
  5. Plays well with components. A React, Vue or Svelte component naturally maps to one BEM block.

Common BEM Mistakes to Avoid

  • Nesting blocks inside element names: .card__header__title is not BEM. Use .card__title instead. Elements are flat by design.
  • Using modifiers without the base class: always write class="card card--featured", never just card--featured alone.
  • Naming after appearance: card--red ages badly. Prefer card--featured or card--promo.
  • Making blocks too big: if a block has 30 elements, it should probably be split into smaller blocks.
css code laptop

BEM vs Other Approaches (Quick Comparison)

Approach Best For Trade-off
BEM Global CSS, large teams, design systems Long class names
Tailwind / Utility-first Fast prototyping, solo devs Cluttered HTML
CSS Modules React / Vue components Requires bundler
Atomic Design Design system thinking More of a structure than a naming rule

A Quick Recipe to Start Using BEM Today

  1. Identify the block: what is this component called? (newsletter, pricing-table, nav…)
  2. List its elements: title, input, button, item, icon.
  3. Decide which variations need a modifier: dark theme, disabled, active, large.
  4. Write the HTML using block, block__element, block--modifier.
  5. Keep selectors flat in CSS, one class per rule.

FAQ About BEM in CSS

What does BEM stand for in CSS?

BEM stands for Block, Element, Modifier. It’s a naming convention that structures class names so the HTML stays readable and the CSS stays maintainable.

Is BEM still used in 2026?

Yes. While utility-first frameworks like Tailwind have grown massively, BEM is still widely used in design systems, WordPress themes, server-rendered apps and any project relying on traditional global CSS.

How does BEM prevent CSS conflicts?

Because every class is prefixed with its block name (for example card__title instead of just title), two components can never accidentally share a selector.

Can I use BEM with Sass or SCSS?

Absolutely. The & parent selector in Sass makes BEM very clean: &__title and &--featured inside a .card block produce the full BEM class names automatically.

Should beginners learn BEM?

Yes. Even if you later switch to Tailwind or CSS-in-JS, understanding BEM teaches you to think in components, which is a skill every modern front-end framework relies on.

Final Thoughts

BEM is not magic, it’s discipline. Once you adopt the block__element--modifier pattern, your stylesheets stop fighting you, code reviews get faster, and onboarding new developers becomes painless. Try it on your next component and compare it side-by-side with your old class names. The difference will speak for itself.