Skip to content
Logo Theodo

How I stopped worrying and learned to love the CSS with BEM

Albéric Trancart10 min read

CSS coding should not be a pain in the neck. At some point, most developers notice that they avoid writing CSS and that it has an impact on their efficiency and on the code quality, which is unacceptable.

It recently happened to me so I decided to tackle this issue. I stopped, took a deep breath and I dived, crawling the Internet looking for a solution.

I eventually found one, and I never despised CSS ever since. In fact, I rewrote the entire CSS stylesheet of my main personal project (its design is entirely custom) and I achieved a 50% drop in CSS lines count and number of classes, in addition to increasing maintainability, reusability and code quality.

In this article, I will cover these subjects:

This article will serve you well if you code your CSS from scratch but it will also help you if you use frameworks like Bootstrap (let’s face it, you can not do everything with a styling framework). I assume that you are using a preprocessor so the LESS syntax will be used in the examples.

Why you should care about CSS

CSS with preprocessors like LESS and SASS is a great tool. But remember: “With great power comes great responsibility”. Having powerful tools like design patterns and awesome frameworks does not mean you will use them without running into trouble. Doing bad, bad, bad things is super easy with CSS and preprocessors. Even if you say “ok, this time I will do it better”, if you do not have some quality standards you will keep writing messy CSS. Let’s see why:

Dealing with selectors

First of all, you must have a good understanding of what specificity is. Here is a nice definition :

Specificity determines which CSS rule is applied by the browsers. If two selectors apply to the same element, the one with higher specificity wins.

The rules to win the specificity war are:

Here is a good website to compute the specificity of a selector: Specificity Calculator. Try it with your own selectors! Now that we fully understand specificity, here are some best practices:

Have decoupled selectors

Separating your selectors is a good idea. For instance, if you have this markup:

<div class="alert danger">...</div>

You should style it with:

/* GOOD */
.alert {
  font-weight: bold;
}
.danger {
  color: red;
}
/* BAD */
.alert.danger {
  font-weight: bold;
  color: red;
}

Decoupling selector will not only increase maintainability and scalability: it will speed up the rendering. Most web browsers are caching first-level selectors. .alert and .danger will be cached but not .alert.danger!

Keep your specificity low

In short, avoid downward selection like hell. With a sufficient amount of CSS, you would end up using inline styles. For instance, this is a very bad selector:

#hellobar a.hellobar_cta.hb-button {
}

In addition to the non-meaningful class names, how would you overwrite a rule set by this selector? Using !important, inline style or just another class, maybe?

To avoid future complication and refrain your inclination to go down in the specificity hell, you should follow these rules:

.danger {
  color: red !important;
}

Don’t mess with HTML or Javascript

Every language exists for a reason and is an autonomous, meaningful entity. CSS is for styling. HTML is for meaning. Javascript is for manipulation.

<a class="clickable"></a>
<li class="clickable"></li>
<tr class="clickable"></tr>
<h3 class="clickable"></h3>

This is particularly useful for single page apps using custom routing links or for a resource that is accessible on click, without page change. If you have a user input (like a text coming from a WYSIWYG textarea), consider making an exception:

.user-input {
    a { .clickable; }
    h1 { .big; }
    kbd { .code; }
}

It is also a good practice to write style-first DOM. Provided you have a nice grid system (flexbox is great), you might consider ordering your properties like this:

For instance, if I have an AngularJS app:

<a flex="50" class="btn  btn-default" href="..." title="..." ng-if="..."></a>

The first step to heaven: OOCSS

If there is one word to describe OOCSS, it is reusability. What is OOCSS?

OOCSS means Object-Oriented CSS. The goal is to find repeated visual patterns and to factorize them when possible. .big-title is better than .main-title while .links-list is prefered to .articles-menu.

Bootstrap was the first great impulsion towards OOCSS. See for yourself:

<a class="btn  btn-default  btn-lg"></a>

Some properties are factorized in the .btn class, reducing code size and speeding up rendering.

But OOCSS has some downsides: sometimes the need is too specific, you can’t address with factorized objects. For instance, building a monolithic web app with an original design is merely impossible with OOCSS only.

Furthermore, it is very difficult to foresee what piece of code will be reused because OOCSS relies on visual patterns and you don’t have any when starting a web app from scratch.

The BEM structure

BEM is a method published in 2010 by Yandex. It means Block Element Modifier. It relies on the fact that every web page or web app can be exploded into blocks, elements and modifiers.

The BEM syntax is a bit specific. The official naming convention is:

.block {
}
.block--modifier {
}
.block__element {
}
.block__element--modifier {
}

Here is a short example which sums up the entire BEM concept:

.Person {
}
.Person--blind {
}
.Person__head {
}
.Person__hand {
}
.Person__hand--left {
}
.Person__hand--right {
}

(I like to start class names with a capital letter because it ensures that the name is not already in use by a vendor like Bootstrap)

BEM Blocks

A block is an autonomous entity, a component of the web app. An app can be represented as Block Tree. For instance, here is an excerpt from the official BEM website:

bem-blocks

A block can even be reused across websites and most of all it has its own context. Which means that higher or lower blocks in the Block Tree will not affect the display of the current block.

To achieve this, positioning rules and BEM blocks should be totally decoupled. A Block class should not contain rules such as float, margin or width.

The main advantage of this is that blocks can be moved across the website without worry. An interesting property is that, as a consequence, blocks can be included recursively. Imagine building a Reddit-like comment tree:

<div class="CommentBox">
  [... Text ...]
  <div class="CommentBox">
    [... Text ...]
    <div class="CommentBox">
      [... Text ...]
    </div>
  </div>
  <div class="CommentBox">
    [... Text ...]
  </div>
</div>

If blocks and positioning rules are properly decoupled, you win!

This is particularly powerful when used in combination with components-based frameworks: AngularJS directives, ReactJS components…

BEM Elements and Modifiers

An element is a part of a block. Thus it uses the block context. That’s why there is a reminder before the element name:

.block__element {
}

Blocks being autonomous entities, elements can and should be positioned inside them. Modifiers are classes used to propose alternative versions of a block or an element. The following example could be described by this markup:

<nav class="Navbar">
  <a class="Navbar__tab">Tab 1</a>
  <a class="Navbar__tab">Tab 2</a>
  <a class="Navbar__tab  Navbar__tab--active">Tab 3</a>
  <a class="Navbar__tab">Tab 4</a>
</nav>

bem-elements

Preprocessors are really useful:

.Navbar {
    ... rules ....

    &__tab {
        ... rules ....

        &--active {
            ... rules ....
        }
    }
}

Elements can also be positioned blocks:

<div class="Search">
  <input class="Search__input  Input" />
  <button class="Search__button  Button"></button>
</div>

Suggested CSS architecture

Now that you have all of this in mind, how to structure your CSS (or LESS/SASS files)? There is no absolute guideline but here is a suggested file tree:

style
├── bootstrap.less
├── components
│   ├── button.less
│   ├── link.less
│   ├── navbar.less
│   └── ...
├── objects
│   ├── colors.less
│   ├── grid.less
│   ├── typo.less
│   └── ...
├── resets
│   ├── fonts.less
│   ├── html.less
│   ├── vendor.less
│   └── ...
└── themes
    ├── theme1.less
    ├── theme2.less
    └── ...

With this, you could easily reuse bits of code and components for your other websites. Creating your own styling framework is at a hand and it is not that difficult!

Conclusion

With OOCSS and BEM, I began to enjoy CSS. Before, it was more drudgery than anything else.

With OOCSS and BEM, the code is more structured, reusable, and you have that feeling that you’re doing it right. Which is, in my opinion, the most important thing because you will be more efficient and produce better quality code.

Sources and inspirations:

Liked this article?