html
/

BEM Methodology: Block-Element-Modifier

Last Sync: Today

On this page

17
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

html

BEM Methodology: Block-Element-Modifier

What is BEM?

BEM (Block-Element-Modifier) is a popular CSS naming methodology that helps create scalable, maintainable, and reusable components. It provides a clear structure for class names, making it easier for teams to collaborate and understand the relationship between HTML and CSS.

Core Concepts

ConceptSyntaxDescriptionExample
Block.blockStandalone component.card, .button, .header
Element.block__elementPart of a block.card__title, .button__icon
Modifier.block--modifier or .block__element--modifierVariation or state.button--primary, .card__title--large

Blocks: Independent Components

CSSRead-only
1
/* Block: standalone component */
.card { }
.button { }
.navbar { }
.modal { }

/* Bad: too specific, not reusable */
.home-page .sidebar .card { }

/* Good: reusable block */
.card { }

/* Block naming: use descriptive names */
.user-profile { }
.search-form { }
.main-navigation { }

Elements: Parts of Blocks

CSSRead-only
1
/* Block */
.card { }

/* Elements (two underscores) */
.card__title { }
.card__image { }
.card__description { }
.card__button { }

/* HTML structure */
/*
<div class="card">
  <img class="card__image" src="...">
  <h2 class="card__title">Title</h2>
  <p class="card__description">Description</p>
  <button class="card__button">Click</button>
</div>
*/

/* Elements can't exist outside their block */
/* Bad: element without block */
.card__title { } /* This is fine as CSS, but HTML must have .card parent */

/* Nested elements (avoid deep nesting) */
/* Good: flat structure */
.card__header { }
.card__header-title { } /* Avoid this - too deep */

/* Better: keep flat */
.card__title { }
.card__subtitle { }

Modifiers: Variations & States

CSSRead-only
1
/* Block modifiers (two hyphens) */
.button { }
.button--primary { }
.button--secondary { }
.button--large { }
.button--disabled { }

/* Element modifiers */
.card__title { }
.card__title--large { }
.card__title--highlighted { }

/* HTML usage */
/*
<button class="button button--primary button--large">
  Submit
</button>

<h2 class="card__title card__title--large">
  Large Title
</h2>
*/

/* Boolean modifiers (presence indicates true) */
.button--disabled { }
.modal--visible { }

/* Key-value modifiers */
.button--size-small { }
.button--size-large { }
.theme--color-dark { }
.theme--color-light { }

Complete Example

HTMLRead-only
1
<!-- HTML Structure -->
<article class="card card--featured">
  <img class="card__image" src="image.jpg" alt="Card image">
  <div class="card__content">
    <h2 class="card__title card__title--large">
      Featured Article
    </h2>
    <p class="card__description">
      This is an amazing article about BEM methodology.
    </p>
    <div class="card__footer">
      <button class="button button--primary button--small">
        Read More
      </button>
      <button class="button button--secondary button--small">
        Save
      </button>
    </div>
  </div>
</article>
CSSRead-only
1
/* CSS Styles */
/* Card Block */
.card {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  overflow: hidden;
}

.card--featured {
  border: 2px solid #ffd700;
  box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}

/* Card Elements */
.card__image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

.card__content {
  padding: 20px;
}

.card__title {
  font-size: 18px;
  margin: 0 0 10px 0;
}

.card__title--large {
  font-size: 24px;
}

.card__description {
  color: #666;
  line-height: 1.5;
  margin: 0 0 15px 0;
}

.card__footer {
  display: flex;
  gap: 10px;
}

/* Button Block (separate component) */
.button {
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-family: inherit;
  padding: 10px 16px;
  transition: all 0.3s ease;
}

.button--primary {
  background: #3498db;
  color: white;
}

.button--primary:hover {
  background: #2980b9;
}

.button--secondary {
  background: #95a5a6;
  color: white;
}

.button--small {
  padding: 6px 12px;
  font-size: 14px;
}

BEM with Preprocessors

SCSSRead-only
1
/* SCSS with nesting (keeps BEM structure readable) */
.card {
  background: white;
  border-radius: 8px;
  
  &--featured {
    border: 2px solid gold;
  }
  
  &__image {
    width: 100%;
    
    &--rounded {
      border-radius: 50%;
    }
  }
  
  &__title {
    font-size: 18px;
    
    &--large {
      font-size: 24px;
    }
  }
  
  &__description {
    color: #666;
  }
  
  &__footer {
    display: flex;
    gap: 10px;
  }
}

/* Output CSS will have proper BEM names */
/* .card, .card--featured, .card__image, etc. */

Common Patterns

CSSRead-only
1
/* Navigation component */
.nav { }
.nav__list { }
.nav__item { }
.nav__link { }
.nav__link--active { }

/* Form component */
.form { }
.form__group { }
.form__label { }
.form__input { }
.form__input--error { }
.form__error-message { }
.form__actions { }

/* Modal component */
.modal { }
.modal--open { }
.modal__overlay { }
.modal__container { }
.modal__header { }
.modal__title { }
.modal__body { }
.modal__footer { }
.modal__close { }

/* User avatar component */
.avatar { }
.avatar--small { }
.avatar--medium { }
.avatar--large { }
.avatar__image { }
.avatar__initials { }
.avatar__status { }
.avatar__status--online { }
.avatar__status--offline { }

BEM File Structure

PLAINTEXTRead-only
1
css/
├── components/
│   ├── button.css
│   ├── card.css
│   ├── modal.css
│   ├── navbar.css
│   └── form.css
├── layouts/
│   ├── header.css
│   ├── footer.css
│   └── sidebar.css
├── pages/
│   ├── home.css
│   ├── about.css
│   └── contact.css
└── main.css

/* Example: components/button.css */
.button { }
.button--primary { }
.button--secondary { }
.button--large { }
.button--small { }
.button--disabled { }
.button__icon { }
.button__text { }

Mixing Blocks

HTMLRead-only
1
<!-- Blocks can be mixed together -->
<div class="card">
  <h2 class="card__title">Title</h2>
  <!-- Button block inside card block -->
  <button class="button button--primary card__button">
    Click
  </button>
</div>

<!-- Multiple blocks on same element -->
<div class="card featured-card">
  <!-- Avoid: mixing BEM with utility classes carefully -->
  <button class="button button--primary mt-2">
    Submit
  </button>
</div>

<!-- Parent-child relationship through classes only -->
<div class="search-form">
  <input class="search-form__input" type="text">
  <button class="search-form__button">Search</button>
</div>

BEM vs Other Methodologies

MethodologyNaming PatternProsCons
BEM.block__element--modifierExplicit, self-documenting, modularVerbose class names
OOCSS.object .childReusable objects, separation of structure/skinLess explicit relationships
SMACSS.l-header, .moduleCategorization, flexibleRequires discipline
Atomic CSS.w-50, .bg-redHighly reusable, small CSSTight coupling to HTML, maintenance

Best Practices

  • Use descriptive names – .user-card not .uc or .card1
  • Avoid deep nesting – Keep elements flat (.block__element not .block__element__subelement)
  • Use modifiers for variations – Not separate blocks
  • Combine with utility classes – For spacing, typography utilities
  • Be consistent – Same naming rules across entire project
  • Document your components – Create a style guide/pattern library
  • Use BEM with CSS-in-JS – Maintains naming consistency
  • Never use IDs for styling – IDs break reusability and specificity

Common Mistakes

  • Over-nesting elements – .card__header__title__icon (too deep)
  • Inconsistent naming – Mixing .card-title, .card__title, .CardTitle
  • Modifiers without base block – Missing .button class when using .button--primary
  • Styling based on parent context – .sidebar .card (breaks encapsulation)
  • Using elements outside blocks – HTML structure must match BEM naming
  • Overly generic names – .box, .container, .wrapper

Real-World Project Example

HTMLRead-only
1
<!-- Complete e-commerce product card -->
<div class="product-card product-card--sale">
  <div class="product-card__badge">
    <span class="badge badge--sale">Sale!</span>
  </div>
  
  <img class="product-card__image" src="product.jpg" alt="Product">
  
  <div class="product-card__content">
    <h3 class="product-card__title">
      <a href="/product" class="product-card__link">
        Product Name
      </a>
    </h3>
    
    <div class="product-card__rating">
      <div class="rating rating--4-5">
        <span class="rating__stars">★★★★☆</span>
        <span class="rating__count">(42 reviews)</span>
      </div>
    </div>
    
    <div class="product-card__pricing">
      <span class="product-card__price product-card__price--original">$99.99</span>
      <span class="product-card__price product-card__price--sale">$79.99</span>
    </div>
    
    <div class="product-card__actions">
      <button class="button button--primary button--full">
        Add to Cart
      </button>
      <button class="button button--secondary button--icon">
        <span class="button__icon">❤️</span>
      </button>
    </div>
  </div>
</div>

Tools & Automation

JavaScriptRead-only
1
// PostCSS plugin for BEM (postcss-bem)
// .block {
//   &__element { }
//   &--modifier { }
// }

// BEM linters
// stylelint-config-bem
// .block {}

// BEM generator tools
// https://bembuilder.js.org/

// VS Code extensions
// "BEM Helper" - generates BEM class names
// "CSS BEM" - autocomplete for BEM structure

BEM with React/Vue Components

React JSXRead-only
1
// React component with BEM
const Card = ({ featured, title, description, children }) => {
  const blockName = 'card';
  const modifier = featured ? `${blockName}--featured` : '';
  
  return (
    <div className={`${blockName} ${modifier}`}>
      <h2 className={`${blockName}__title`}>{title}</h2>
      <p className={`${blockName}__description`}>{description}</p>
      <div className={`${blockName}__content`}>{children}</div>
    </div>
  );
};

// With CSS Modules and BEM
import styles from './Card.module.css';
// styles = { card: 'card_xyz', card__title: 'card__title_abc' }

const Card = () => (
  <div className={styles.card}>
    <h2 className={styles['card__title']}>Title</h2>
  </div>
);

Conclusion

BEM methodology provides a clear, scalable approach to CSS architecture. By using consistent naming patterns (Block__Element--Modifier), teams can build maintainable components that are reusable, self-documenting, and resistant to style conflicts. While class names become more verbose, the benefits of predictability and encapsulation far outweigh the costs for large-scale projects.

Try it yourself

/* Try BEM naming! */
.user-card {
  background: white;
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  max-width: 300px;
  font-family: system-ui;
}

.user-card--featured {
  border: 2px solid #ffd700;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.user-card__avatar {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  margin-bottom: 15px;
}

.user-card__name {
  font-size: 20px;
  margin: 0 0 5px 0;
}

.user-card__name--large {
  font-size: 24px;
}

.user-card__role {
  color: #666;
  margin: 0 0 15px 0;
}

.user-card__button {
  background: #3498db;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.2s;
}

.user-card__button:hover {
  background: #2980b9;
}

Test Your Knowledge

Q1
of 5

What does BEM stand for?

A
Block, Element, Modifier
B
Base, Element, Method
C
Block, Extension, Modifier
D
Basic, Extended, Modern
Q2
of 5

Which syntax is correct for a BEM element?

A
.block-element
B
.block__element
C
.block--element
D
.block_element
Q3
of 5

Which syntax is correct for a BEM modifier?

A
.block__modifier
B
.block--modifier
C
.block_modifier
D
.block-modifier
Q4
of 5

Can an element exist without its block in HTML?

A
Yes, always
B
No, never
C
Only with modifiers
D
Only for global elements
Q5
of 5

Which is the recommended nesting depth for BEM elements?

A
Unlimited nesting
B
Maximum 2 levels
C
Keep flat (avoid deep nesting)
D
Must have exactly 3 levels

Frequently Asked Questions

What does BEM stand for?

Block, Element, Modifier – a CSS naming methodology for creating reusable components.

Why use double underscores and hyphens?

Convention: __ for elements, -- for modifiers. This creates visual distinction and makes relationships clear.

Can I nest BEM elements?

Avoid deep nesting (like .block__element__subelement). Keep flat: .block__element and .block__subelement.

Does BEM work with CSS-in-JS?

Yes! BEM principles (encapsulation, naming patterns) apply well to CSS-in-JS solutions like styled-components.

Should I use BEM with utility frameworks like Tailwind?

They can coexist. Use BEM for component structure and Tailwind utilities for spacing, colors, etc. Or choose one primary approach.

Previous

css performance

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.