Laura Chan

Quick notes on BEM (Block Element Modifier) syntax in CSS

What is it?

  • What it's not:

    • A CSS framework (like Bulma, Bootstrap)
    • Library
  • It's a naming convention for classes in HTML and CSS
  • Alternatives of naming conventions include

    • Object Oriented CSS (OOCSS)
    • Scalable and Modular Architecture for CSS (SMACSS)
    • Atomic CSS

How to use it

  • Block: higher level component
  • Element: descendent of block, relies on block
  • Modifier: represents different state or version of block/element
.block {
}
.block__element {
}
.block--modifier {
}

For example, in JSX:

<div
  className={`block ${isSelected ? "block--selected" : ""} ${
    warning ? "block--warning" : ""
  }`}
>
  <div className="block__element"></div>
</div>

A 'real world' example:

.person {
}
.person__hand {
}
.person--male {
}
.person--male__hand {
}
.person__hand--left {
}

A real world example

Before BEM

.site-search {
}
.site-search.full {
}
.site-search .field {
}
<form class="site-search full">
  <input type="text" class="field" />
  <input type="Submit" value="Search" class="button" />
</form>
  • Problem with above is that the full class and the field class might clash with class styles defined elsewhere

With BEM

.site-search {
} /* Block */
.site-search__field {
} /* Element */
.site-search--full {
} /* Modifier */

or

.site-search {
  /* Block */
  &__field {
  } /* Element */
  &--full {
  } /* Modifier */
}
<!-- Notice that a modified element gets both the base block class and the modifier class -->
<form class="site-search  site-search--full">
  <input type="text" class="site-search__field" />
  <input type="Submit" value="Search" class="site-search__button" />
</form>

Pros and cons

  • πŸ‘ Avoids name clashing against global scope
  • πŸ‘ Clear what to name a new class
  • πŸ‘ Clear understanding of how CSS matches up with HTML - clear what modifier should go with what block
  • πŸ‘ Follows components
  • πŸ‘ Maintains flexibility in a CSS world - so we are still open to mix in personal preferences - but this is still open to lack of consistency across a team

When mixed with global styles like the below, it's flexible, but a new developer would need to know these helpers existed to use them.

.noBreakText {
  white-space: nowrap;
}
.upperCase {
  text-transform: uppercase;
}
  • πŸ‘Ž Other tools out there which solve the global scope problem (CSS modules, SvelteJS, Styled Components (React specific))
  • πŸ‘Ž Lack of clarity on what should be an 'atomic' modifier
  • πŸ‘Ž Is open to unnecessary nesting - when is something a new block? When does something need a new modifier?

e.g.

<div class="header">
  <div class="logo"></div>
</div>

or

<div class="header">
  <div class="header__logo"></div>
</div>

Resources

Back to blog