Better CSS organization with the BEM syntax

BEM is a great structured methodology for writing CSS/SASS. It's a simple syntax that allows you to write CSS faster (no more scratching your brain trying to come up with logical naming conventions), write CSS that is more organized, and provides you with an easier way to communicate CSS across projects with colleagues, future employees, and contractors.

An example

Let's take this Chuck Norris fact module I tossed together to demonstrate.

Chuck Norris

Fact: "Chuck Norris’ keyboard only has 2 keys: 0 and 1."

The Codes

<style>
  .fact { text-align: center; max-width: 340px; margin: 40px 0; }
  .fact__image { padding: 10px; margin: 15px; border: 1px solid #000; max-width: 100%}
  .fact__name { font-size: 20px; text-transform: uppercase; }
  .fact__quote { font-style: italic; }
</style>

<div class="fact">
  <img class="fact__image" src="chuck-norris-uzis.jpg">
  <p class="fact__name">Chuck Norris</p>
  <blockquote class="fact__quote"> 
      Fact: "Chuck Norris’ keyboard only has 2 keys: 0 and 1." 
  </blockquote>
</div>

Breaking down BEM

The principals of BEM are simple. You break each piece of your markup down into individual pieces, and each one of those pieces falls into one of three categories:

B: a block

E: an element - appended on the block name starting with two underscores

M: a modifier - appended on the element name starting with two dashes

<style>
    .block {}
    .block__element {}
    .block__element--modifier {}
</style>

The syntax can appear a bit strange the first time you see it, and a little verbose, but verbosity can provide clarity. Let's run through each one and use our Chuck Norris example to make sense of it.

Block

You can think of your block as the most outer container of a module. Good examples include the header, a sidebar, testmonial module, or in our case, a Fact module. To declare our fact module we start with a DIV with the class name fact. This is what we will prepend all descendents of the Fact module. Now anytime we see some code starting with "fact" we immediately know what we're working with!

Element

An element is a smaller chunk of markup that is a descendent of the block as a whole. In our Fact module this includes the "name" .fact __name, the image .fact__image, and the fact quote .fact__quote. Again, this helps us understand the element belongs to a particular block.

Modifier

A modifier "modifies" (brain buster right?) an element. Modifiers allow us to tack on different states to an element, and still have an understanding how it relates to the module.

Let's take our Fact Module and modify it. Say we want to create a Patriotic version of our Fact Module by giving it some red, white, and blue styling, by putting some borders around the image. With BEM syntax, we would do the following -

We retain the earlier CSS we already created such as -

.fact__image { padding: 10px; margin: 15px; border: 1px solid #000; max-width: 100%}

but we tweak it by adding an additional modifier class that supplements (not replaces) the original .fact__image class -

.fact__image--patriotic {  border: blue 8px solid; outline: 8px solid red; }

and so our markup would now include both classes -

<img class="fact__image fact__image--patriotic" src="..">

Chuck Norris

Fact: "Chuck Norris puts the fist in pacifist. "

You may be tempted to take our current class .fact__image and simply tack on a patriotic class, so what we would have would look like class="fact__image patriotic", then write some CSS that targets the patriotic class. That's often the approach taken, however BEM takes a more specific approach. Using the BEM syntax makes it clear that the patriotic styling is specific to this Fact block and image element. This can be particularly useful when working with a large code base with several team members responsible for writing HTML and CSS. While this example is a bit contrived, if we simply passed on a patriotic class, there is a greater chance another use of patriotic not intended for this module could override its styles, or vice versa. The more generic the class names used, the more likely this issue can arise, which is not surprisingly common in a large code base, or a code base that accumulates new authors.

Scratching the surface

We've only scratched the surface here of demonstrating the usefulness of the BEM syntax. To learn more, check out the Yandex folks that defined the BEM methodology.

Questions, comments, improvements?