Skip to content

BEM with LESS

BEM (Block, Element, Modifier) is a naming convention that keeps component styles predictable and free of specificity conflicts. LESS's parent selector makes writing BEM components significantly less repetitive.

What Is BEM, and Why Pair It with LESS?

BEM structures class names as block, block__element, and block--modifier, keeping every class flat (single-class specificity) while still communicating structure and relationships through naming alone.

Written in plain CSS, BEM requires repeating the block name in every element and modifier class. LESS's & parent selector eliminates that repetition, letting you nest elements and modifiers inside the block's rule while still compiling to flat, BEM-correct selectors.

.card {
  padding: 1rem;
  border-radius: 8px;

  &__title {
    font-size: 1.25rem;
    font-weight: 700;
  }

  &__body {
    color: #4b5563;
  }

  &--featured {
    border: 2px solid gold;
  }
}

Compiles to flat, single-class selectors: .card, .card__title, .card__body, and .card--featured.

BEM Naming with & Syntax

.block {
  &__element { }
  &--modifier { }
  &__element--modifier { }
}
  • &__element compiles to .block__element, a child part of the block.
  • &--modifier compiles to .block--modifier, a variant of the block itself.
  • &__element--modifier compiles to .block__element--modifier, a variant of a specific element.
  • No space is used between & and the double underscore or double hyphen.

BEM with LESS Cheatsheet

Common BEM patterns expressed with LESS's parent selector.

BEM Concept LESS Pattern Compiled Selector
Block .card { } .card
Element &__title { } .card__title
Modifier &--featured { } .card--featured
Element modifier &__title--large { } .card__title--large
Modifier affecting element &--featured &__title { } .card--featured .card__title

Modifiers That Affect Child Elements

A common BEM pattern styles a nested element differently when a parent modifier is active, which LESS expresses cleanly by nesting the element's selector inside the modifier's block.

.card {
  &__title {
    color: #111;
  }

  &--featured {
    border: 2px solid gold;

    &__title {
      color: #b45309; // .card--featured .card__title
    }
  }
}

Keeping BEM Specificity Flat

The core promise of BEM is flat, single-class specificity. It's important that LESS's nesting convenience doesn't accidentally produce deeply chained, high-specificity selectors that undermine that promise.

  • Avoid nesting BEM elements inside other elements' selectors, keep each element flat relative to its block.
  • Reserve nested modifier-affecting-element patterns for genuine parent-child relationships, not convenience.
  • Periodically inspect compiled CSS to confirm selectors remain flat, single or double-class combinations.

Combining BEM with Mixins

BEM's structural naming and LESS mixins solve different problems and combine well: BEM organizes a component's class names, while mixins share cross-component behavior like resets or shadows within that structure.

.badge {
  .reset-list-style();
  padding: 0.25rem 0.5rem;
  border-radius: 999px;

  &--success { background: #dcfce7; color: #166534; }
  &--danger  { background: #fee2e2; color: #991b1b; }
}

Common Mistakes

  • Nesting BEM elements inside other elements, producing selectors like .card__body .card__title instead of flat, sibling-level classes.
  • Forgetting that &__element--modifier (element with its own modifier) differs from &--modifier &__element (element affected by a block modifier).
  • Overusing deeply nested modifier-affecting-element patterns where a simpler, separate class would be clearer.
  • Mixing BEM naming with unrelated, non-BEM utility classes inconsistently within the same component.

Key Takeaways

  • BEM structures class names as block, block__element, and block--modifier for flat, predictable specificity.
  • LESS's & parent selector removes the repetition BEM would otherwise require in plain CSS.
  • &--modifier &__element styles a child element based on an active parent modifier.
  • Combine BEM's naming structure with mixins for shared cross-component behavior within that structure.

Pro Tip

Periodically inspect your compiled CSS output for a BEM component, if you see any selector deeper than two classes chained together, it's a sign your LESS nesting has drifted from BEM's flat-specificity principle.