DEV Community

Dave O'Dea
Dave O'Dea

Posted on

Explain CSS BEM Structures Like I'm Five

I) What are they?
II) How and why are they used?
III) What are some recommend resources for further learning?

Cheers,
Dave

Top comments (7)

Collapse
 
isaacdlyman profile image
Isaac Lyman • Edited

In traditional webapps (i.e. webapps built before CSS encapsulation was invented), every CSS rule is shared by the entire app. This creates a few problems:

1) the "acupuncture effect": you modify a style on a button on page A, and suddenly an input on page C is broken. If you've worked on a large web project you've probably got a few gray hairs because of this.
2) fragmentation: one developer uses really explicit class names, e.g. .button-on-the-checkout-page-underneath-the-subtotal, another uses brief class names, e.g. .btn, and yet another uses IDs instead of classes (shudder).
3) fighting the cascade: you write some styles for an element, save, reload, and none of the styles have any effect. You inspect the page and someone else's styles have greater specificity than yours. You have to invent a random way to add specificity to your rule so that your styles will show up, without also wrecking every other element that uses the old styles.

BEM is not a plugin, a library or a framework. It's a set of rules you can adopt to make CSS easier to work with in your project. It stands for "Block, Element, Modifier" and, in short, it gives you the following rules:

1) Every CSS selector should use a single unique class name, not a tag, an ID, or an attribute.
2) Every element in your app should have its own special class.
3) An app is a set of components (known as "blocks" in BEM), and each component has several HTML elements (the E in BEM). Sometimes elements look different depending on the state of your app (different states are "modifiers" in BEM).
4) CSS classes are constructed like this: block__element--modifier. Hyphens are used for multi-word blocks, elements, or modifiers.

So a component in an AngularJS app that follows BEM could look like this:

<div class="week-calendar">
  <div class="week-calendar__header"></div>
  <div class="week-calendar__body"></div>
  <div class="week-calendar__actions">
    <button class="week-calendar__save"
      ng-class="{ 'week-calendar__save--saving': ctrl.saving }">
      Save
    </button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

And the stylesheet would look like this:

.week-calendar { height: 200px; width: 300px; }
.week-calendar__header { height: 40px; }
.week-calendar__body { height: 140px; }
.week-calendar__actions { height: 20px; }
.week-calendar__save { background-color: green; cursor: pointer; }
.week-calendar__save--saving { background-color: gray; cursor: default; }
Enter fullscreen mode Exit fullscreen mode

Or, with a preprocessor like SASS:

.week-calendar {
  height: 200px;
  width: 300px;

  &__header { height: 40px; }
  &__body { height: 140px; }
  &__actions { height: 20px; }
  &__save {
    background-color: green;
    cursor: pointer;

    &--saving {
      background-color: gray;
      cursor: default;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

When you use BEM, you can look at any class name and know what element it applies to. Specificity never gets out of control, because each element has its own class. And styles meant for specific components won't affect other parts of the app. If you don't have access to CSS encapsulation via a modern solution like Vue, React, CSS Modules, or Angular 2+, this is a great way to keep your style sheets sane.

Collapse
 
craser profile image
Chris Raser

That's a great explanation.

Collapse
 
miku86 profile image
miku86

Hey Isaac,

thanks for your explanation,
especially for the part about the traditional problems.

Collapse
 
caiorcferreira profile image
Caio Ferreira • Edited

Great explanation, thanks!
Just a question, from a readability point of view, you'd say that it is valid to use even in React or other frameworks?

Collapse
 
isaacdlyman profile image
Isaac Lyman

That's a hard one. Last I checked, the "official" solution for styling React apps is CSS-in-JS, which uses the HTML style attribute, which makes BEM irrelevant. However, if you decide to style your app with traditional CSS files (or <style> tags), then yes, BEM is valid.

As far as other frameworks, it depends. Angular 2+ and Vue (with Single File Components) have CSS encapsulation, so BEM, while still valid, is probably solving a problem you don't have.

There are a few other good CSS architectures worth considering as well, like SMACSS and Atomic. And rolling your own is fine too.

Collapse
 
davedodea profile image
Dave O'Dea

Great, thank you Isaac.

Collapse
 
deadcoder0904 profile image
Akshay Kadam (A2K)