BEM Naming in CSS

BEM naming in CSS is a class naming method that helps you write clear, predictable, component-based styles. BEM stands for Block, Element, Modifier. It is not a CSS feature built into the browser. It is a convention for naming classes so developers can understand structure and purpose from the class name itself.

CSS can become hard to maintain when class names are vague, selectors are deeply nested, or the same name means different things in different places. BEM solves this by making relationships explicit. A class name tells you what component it belongs to, what part of the component it styles, and whether it represents a variation or state.

What BEM Means

PartMeaningExample
BlockA standalone componentcard
ElementA part inside a blockcard__title
ModifierA variation or statecard–featured

The common BEM syntax uses double underscores for elements and double hyphens for modifiers. The exact characters are a convention, but the idea is more important than the punctuation.

Block in BEM

A block is an independent component that can stand on its own. Examples include card, button, navbar, modal, article-preview, and pricing-table. A block should not depend on a specific parent selector to work.

<article class="card">
  <h2 class="card__title">CSS Reset</h2>
  <p class="card__text">A clean baseline for browser styles.</p>
</article>

The card block can be moved to another section without changing its class names. That portability is one of the main reasons BEM works well for component systems.

Element in BEM

An element is a smaller part of a block that does not make sense as a standalone component. A card can have a title, image, text, footer, badge, and button area. These are elements of the card.

.card {}
.card__image {}
.card__title {}
.card__text {}
.card__footer {}

An element name should describe its role inside the block. Avoid naming elements only by appearance. For example, card__title is usually better than card__big-text because the text size may change later.

Modifier in BEM

A modifier represents a variation, state, or version of a block or element. It changes how something looks or behaves without creating a completely different component.

<article class="card card--featured">
  <h2 class="card__title">Featured Post</h2>
</article>
.card {
  border: 1px solid #e5e7eb;
  padding: 1.5rem;
}

.card--featured {
  border-color: #2563eb;
  background: #eff6ff;
}

The modifier does not replace the block class. It works with it. The element is still a card, but it has a featured version.

BEM Class Naming Syntax

PatternUseExample
blockMain componentmenu
block__elementPart of componentmenu__item
block–modifierComponent variationmenu–compact
block__element–modifierElement variationmenu__item–active

This syntax keeps selector specificity low because most styles use one class selector. Low specificity makes overrides easier and reduces the need for !important.

BEM CSS Example

.button {
  display: inline-flex;
  align-items: center;
  border-radius: 3px;
  padding: 0.75rem 1rem;
}

.button__icon {
  margin-right: 0.5rem;
}

.button--primary {
  background: #2563eb;
  color: white;
}

.button--small {
  padding: 0.5rem 0.75rem;
}

Each selector has a clear job. The base button defines normal button structure. The icon element styles a part inside the button. The modifiers create variations without writing nested selectors.

Why BEM Helps Large CSS Files

BEM reduces naming collisions. A class like title can mean many things across a site. A class like card__title clearly belongs to the card block. This is useful when multiple developers work on the same stylesheet or when a project grows over time.

BEM also makes deletion safer. If you remove a component, you can search for its block name and find related CSS, HTML, and JavaScript hooks more easily. This is harder when class names are generic or deeply connected to page layout.

BEM and Nesting

BEM works best with shallow selectors. You do not need to write .page .section .card .card__title. The class name already contains the relationship. Deep nesting increases specificity and makes styles depend on exact HTML structure.

/* Better */
.card__title {
  font-size: 1.5rem;
}

/* Avoid when possible */
.content .grid .card h2 {
  font-size: 1.5rem;
}

The first selector is reusable. The second selector works only in one structural context and can break when the layout changes.

BEM in WordPress and Gutenberg

In WordPress, BEM is useful for custom blocks, theme sections, reusable patterns, and shortcode output. WordPress and plugins already generate many classes, but your custom classes can still follow BEM to keep your CSS predictable.

For example, a custom tutorial card can use tutorial-card, tutorial-card__label, tutorial-card__title, and tutorial-card--beginner. The names remain understandable even when the card appears inside different templates or sidebars.

When BEM Is Too Much

BEM is helpful, but not every tiny style needs a long BEM class. Utility classes, design system tokens, and small one-off layout helpers can still be useful. The goal is maintainability, not forcing every selector into one naming pattern.

Use BEM for components that repeat, have internal parts, or need variations. For a single simple wrapper, a short semantic class may be enough.

Choosing Good Block Names

A block name should describe the component, not the page where it appears. For example, author-card is better than homepage-box if the same component may later appear on an article page or sidebar. Page-based names become misleading when designs are reused.

Good block names are specific enough to avoid collisions but not so specific that they describe temporary content. Names like pricing-card, lesson-list, course-banner, and site-header are easier to maintain than names like blue-section or top-area.

State Modifiers vs Design Modifiers

Modifiers can describe a design variation or a state. A design modifier might be button--primary, while a state modifier might be accordion__item--open. Keeping this difference clear helps developers know whether the class is controlled by design, content, or JavaScript behavior.

<button class="button button--primary button--loading">
  Saving
</button>

Here, button--primary describes the visual type of button. button--loading describes the current state. Both are modifiers, but they communicate different kinds of information.

BEM and JavaScript Hooks

Some teams use BEM classes for styling and separate classes for JavaScript hooks. This prevents style class names from being tightly coupled to scripts. A common pattern is to use a class like js-menu-toggle only for JavaScript selection and keep BEM classes for presentation.

<button class="menu__toggle js-menu-toggle">
  Menu
</button>

This makes refactoring safer. A designer can rename or restructure styling classes without accidentally breaking JavaScript behavior, as long as the JavaScript hook remains stable.

Refactoring Existing CSS to BEM

You do not need to rewrite an entire website at once to use BEM. Start with one repeated component that has messy selectors. Identify the block, list its internal elements, then convert variations into modifiers. After that, replace deep selectors with direct class selectors.

For example, a selector like .sidebar .box h3 might become .info-card__title. The new class explains the component role and no longer depends on being inside a sidebar. This makes the component portable.

BEM with Utility Classes

BEM and utility classes can work together. BEM handles component identity and structure. Utilities can handle small spacing, alignment, or display tweaks when the project allows them. The important rule is to avoid making utilities silently override important component behavior.

If the same utility override appears every time a component is used, that style probably belongs inside the BEM component itself. Utilities are best for context-specific adjustments, not for fixing incomplete component CSS.

BEM File Organization

BEM becomes more powerful when the CSS file is organized by component. Keep the base block selector, its elements, and its modifiers near each other. This lets a developer scan one section and understand the full component instead of hunting through the stylesheet.

/* Card */
.card {}
.card__title {}
.card__text {}
.card--featured {}

This organization also helps during reviews. If a new modifier is added far away from the original block styles, it is easy to miss conflicts. Keeping related selectors together makes the cascade easier to reason about.

BEM and Responsive Design

Responsive styles can still use BEM selectors. The class name does not need to mention the breakpoint. For example, avoid names like card--mobile if the modifier only exists because of screen size. Use media queries to change the same component instead.

A modifier should represent a meaningful variant, not a temporary viewport condition. If a card is compact because it is a special card type, card--compact makes sense. If it is compact only on small screens, a media query is cleaner.

BEM Review Checklist

Before shipping BEM CSS, read the HTML and ask whether the class names explain the component without seeing the design mockup. If the names are understandable, reusable, and not tied to one page location, the naming is probably healthy.

Also check whether every modifier has a base block class beside it. A modifier alone usually does not contain enough styling context.

BEM Naming Rules

  • Use meaningful block names.
  • Use elements only for parts inside a block.
  • Use modifiers for states and variations.
  • Keep selectors shallow.
  • Do not depend on tag names for component styling.
  • Avoid generic names like title, box, red, or big.
  • Keep class names connected to purpose, not temporary appearance.

Common BEM Mistakes

  • Creating elements of elements, such as card__header__title.
  • Using modifiers without the base block class.
  • Making every small utility a BEM class.
  • Naming by color or size instead of role.
  • Writing deeply nested selectors even after using BEM names.
  • Using BEM only in CSS but not consistently in HTML.

BEM Naming in CSS FAQ

What is BEM in CSS?

BEM is a CSS class naming convention based on Block, Element, and Modifier.

Is BEM a CSS framework?

No. BEM is a naming method, not a framework or browser feature.

Why use double underscores in BEM?

Double underscores separate a block from an element, such as card__title.

Why use double hyphens in BEM?

Double hyphens identify a modifier, such as button–primary.


Continue learning CSS in order
Follow the topic sequence with the previous and next lesson.