Saturday, January 26, 2013

BEM: The Block, Element, Modifier Approach To Decoupling HTML And CSS

For the last couple of months I’ve been thinking a lot about giving our css best practices a refresh and along the way have looked at approaches such as OOCSS, SMACSS, and DRY CSS. They all have some common underlying principles, one of which is the separation of structure and presentation.

We’ve all had this goal for years, but our practices haven’t really achieved it. Instead of decoupling our html and css we’ve been locking them ever tighter and making them more and more dependent on each other. I apologize if you’re getting tired of hearing me talk about coupling, but I think it’s a very important concept to understand if you want to develop scalable and maintainable websites.
 I want to touch on a few of the points and then give a quick walk through of yet another method (BEM) with similar goals to the ones we’ve been talking about.
Rusty chain around a tree with one broken link

Decoupling HTML and CSS

Ideally we’d like to be able to completely rewrite our html or css without touching the other. That’s unlikely to happen all the time. There will often be a need to changes one after changing the other. However the less dependent our html and css are on each other, the better. Using OOCSS we reduce coupling by dropping descendent selectors in favor of classes. With a DRY CSS approach we’re also using classes, but here the magic is based more on how we organize our css around stylistic groups. SMACSS falls somewhere in between these approaches.
All agree we should move away from location based selectors as tying css selectors to a specific html structure leads to greater difficulty in changing either html or css. Inevitably we’re left managing specificity.
Jonathan Snook refers to this as the depth of applicability or in his words, “the depth at which a particular rule set impacts the elements around it.”
For example consider the following code for a relatively simple navigation bar with a single drop down.
<ul id="nav">
  <li><a href="">Item 1</a></li>
  <li><a href="">Item 2</a>
      <li><a href="">Sub Item 1</a></li>
      <li><a href="">Sub Item 2</a></li>
  <li><a href="">Item 3</a></li>
If we were to write some css targeting the link in the drop down ( #nav li a ), the depth of applicability is 5. Even though we didn’t specifically mention every element along the way we’ve moved through ul#nav to li to ul to li to a, or 5 levels of html structure.
That’s too much and it also affects both the top level links and secondary links in the drop down. Jonathan offers two ways to reduce the depth of applicability
  • Child selectors — using #nav > li > a limits the scope to the top level links
  • Class selectors — is ultimately the better approach as it’s not dependent on html structure at all
Jonathan offers some additional explanation and examples in the Smashing Magazine article, which is worth a read if you’ve yet to see it.
The key is in seeing that many of the selectors we’ve been using over the years are coupling our html and css ever tighter. The debate is still ongoing as to the best way to decouple things, though hopefully you agree there’s a need for decoupling.
Lego blocks scattered on a table

BEM — Block, Element, Modifier

The BEM approach to developing websites comes from the developers at Yandex. It has similar goals to the approaches we’ve seen before.
  • Quick development
  • Team efficiency
  • Scalability
  • Code reuse

Blocks and Elements

Under BEM a block is it’s own independent entity. Blocks can be simple or complex and they can contain other blocks. There’s something familiar in this as every html element is displayed as a box or block of some kind.
At the highest level of a design, your blocks might be your header block, footer block, main content block, and sidebar block. Your header would likely include several blocks inside such as one for your logo and tagline, another for a navigation bar, and maybe another making up a search field and button.
Elements are parts of blocks. They perform certain functions within the block and they’re context dependent. Take an element outside its block and it no longer makes sense. For example a search block might be made up of 2 elements.
  • Input field
  • Button
Removing one doesn’t make sense as the block would no longer function correctly.
Together blocks and elements are arranged in your design to form your page layout. Elements are arranged inside blocks and blocks are arranged inside other blocks working up to the outermost container blocks that shape the page as a whole.
Blocks and elements should have keywords (names) associated with them. The only way the same name or keyword is reused is when the same block or element is being reused. Blocks must be independent of each other to allow for arbitrary placement within the design. We want to be able to take our search block and easily move it from the top right in the header to the middle of the sidebar for example.
This leads to 3 guidelines for writing css:
  • Blocks should have unique names, which become classes
  • HTML elements should not be used in css selectors since they aren’t context-free
  • Cascading selectors for several blocks should be avoided
Here again it’s the use of classes that aims to solve the problem of coupling. We’re also encouraged to avoid location based selectors (context dependent) to help decouple our code.
A single white golf tee amidst a sea or orange tees


What happens when you have a block like a search input and button and you want to add another to the page that looks similar, though not exactly like the first? This is where modifiers come in. Modifiers help us create similar though different blocks from already existing blocks.
A modifier is a property of a block or an element that alters its look or behavior. A modifier has a name and a value. Several modifiers can be used at once.
Typically a modifier will be an additional css class you would add to an element. An example I’m sure you’ve come across is highlighting the currently selected menu item so it stands out from the rest of the menu items. To achieve this you probably created css similar to the following.
.current {
  background: #f00;
You’d then added class=”current” to the currently selected menu item. The class modifies one element inside your navigation block.
BEM goes a lot further than what I’ve described above. In fact it’s for more than just html and css. It covers behaviors with Javascript, though the same basic principles and approach apply. I’ll let you read the original source if you’d like more details. I mainly wanted to show you the basic approach.
The idea of seeing a web page as elements within blocks within blocks is an easy one to grasp and probably how many of us already view the pages we develop. I certainly have, as you can see in a couple of posts I wrote for Onextrapixel a couple years back.
Model of Le Corbusier's Villa Savoye built with Lego


Again I hope I’m not repeating myself too much in all these posts, but these concepts are important ones to understand. Ultimately I think we should be rethinking some of our css practices as they haven’t been as great as we’d like to believe. Many have been thinking the same thing and over the last few years we’ve seen quite a few new methods and approaches for writing html, css, and javascript.
Most of these methods are similar in their underlying goals and principles, which is the main thing to be paying attention to. You’ll likely pick and choose techniques across some of these approaches depending upon the specific problem in front of you as opposed to following any one entirely.
It’s the underlying principles like decoupling html and css that are more important. It’s the idea of reducing location based selectors, mostly likely through a greater use of classes that you should be thinking about. See how each approach attempts to solve this and decide which makes the most sense for you.
If you’re getting tired of these posts please let me know. I realize I’ve been offering a lot about this same basic concept for awhile and perhaps the message has long since gotten across. If you are enjoying these posts and some of the methods I’ve been pointing to, let me know as well. There are more approaches out there with similar goals in mind that I could cover.

No comments:

Post a Comment