BEM and CSS Naming Conventions

BEM stands for Block, Element, Modifier. A block is a standalone component such as .card, an element is a part that only makes sense inside it, written .card__title with two underscores, and a modifier is a variation written .card--featured with two hyphens. Modifiers are added next to the base class, never instead of it.

BEM in one table
PartPatternExample
Blockblock.search-form
Elementblock__element.search-form__input
Block modifierblock--modifier.search-form--compact
Element modifierblock__element--modifier.search-form__button--disabled
Key and value modifierblock--key-value.search-form--theme-dark

Updated

Naming is where CSS projects either stay tidy or slowly turn into a pile of overrides. This page explains the BEM rules from the official BEM site, checks your own class names as you type, and compares BEM with the other ways teams keep styles from colliding today.

BEM class name builder

Type a block, element and modifier to get class names, matching HTML and CSS, with warnings when a name breaks a rule.

BEM compared with other approaches

Ways to keep class names from colliding
ApproachExampleWho keeps names uniqueBest fit
BEM.card__title--largeYou, by conventionPlain CSS, Sass, CMS themes
Utility classes (Tailwind)text-lg font-semiboldNo component names neededApps built from components
CSS Modulesstyles.cardTitleThe build tool rewrites namesReact, Vue and similar with a bundler
@scope@scope (.card) { h2 {} }The browser limits the rulesNewer browsers, light markup

A full BEM component

Card block with elements and modifiers

Each selector is one class. The featured modifier changes the border and lets one element react through the block modifier.

<style>
  .card { max-width: 280px; padding: 16px; border: 1px solid #e2e8f0; border-radius: 12px; margin-bottom: 10px }
  .card--featured { border: 2px solid #2563eb }
  .card__title { margin: 0 0 4px; font-size: 18px }
  .card__price { margin: 0; font-weight: 700 }
  .card--featured .card__price { color: #2563eb }
  .card__tag { display: inline-block; font-size: 12px; padding: 2px 8px; border-radius: 99px; background: #f1f5f9 }
  .card__tag--new { background: #dcfce7 }
</style>
<article class="card">
  <h3 class="card__title">Starter</h3>
  <p class="card__price">$9</p>
</article>
<article class="card card--featured">
  <span class="card__tag card__tag--new">New</span>
  <h3 class="card__title">Team</h3>
  <p class="card__price">$29</p>
</article>

Common BEM mistakes

Wrong and right
WrongRightWhy
.card__body__title.card__titleElements belong to the block, not to other elements
class="card--featured"class="card card--featured"A modifier needs its base class
.card .card__title.card__titleExtra nesting adds specificity
div.card__title.card__titleBEM selectors use class names only
.card--blue.card--primaryName the meaning, not the colour

The problem naming conventions solve

Every CSS class lives in one global namespace. Two developers writing .title in different files will eventually style each other's headings, and the usual fix, a longer selector, starts a specificity arms race.

A convention gives every class an owner. When .pricing-card__price misbehaves you know which component to open, and you can delete the component knowing its classes are not used elsewhere.

When blocks contain blocks

A block may sit inside another block. A button in a card stays .btn, and if the card needs to position it, the same element can carry both classes: class="btn card__action".

This mix keeps the button's own styles reusable while the card controls only layout, such as margin or alignment, through its element class.

Native CSS scoping is catching up

@scope lets you limit rules to a subtree, for example everything inside .card but not inside a nested .card__media. It reached Baseline as newly available in 2026, so check your audience's browsers before relying on it alone.

Cascade layers solve a related problem: they let you rank whole groups of styles, so a reset or a third-party theme never outranks your components no matter how specific its selectors are.

How it works

  1. Type a block name, then optionally an element and a modifier, in the builder.
  2. Read the generated class names and the HTML that uses them. Warnings appear when a name breaks a BEM rule.
  3. Copy the HTML and CSS skeleton into your component.

Tips

Frequently asked questions

What does BEM stand for?

Block, Element, Modifier. It is a naming method for CSS classes that keeps every selector to a single class, so specificity stays flat and you can tell from a class name which component it belongs to.

Why does BEM use double underscores and double hyphens?

Single hyphens are already used inside names, as in search-form. Doubling the separators makes the boundary between block, element and modifier unambiguous, so .search-form__submit-button reads as one block and one element.

Is BEM still worth using with Tailwind or CSS Modules?

With utility classes you rarely write component class names, so BEM matters less. With CSS Modules the build tool scopes names for you, and short camelCase names are recommended. BEM is still a strong choice for plain CSS, Sass, WordPress themes and design systems shared across frameworks.

How do I name an element inside an element?

Attach it to the block, not to the parent element. A title inside a card body is .card__title, even when the HTML nests it inside .card__body. If the nested part is reusable on its own, make it a new block instead.

Related: CSS selectors cheat sheet, CSS specificity calculator, CSS frameworks compared, CSS variables, Modern CSS reset.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Guides

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap