Building a modular My Health Skills with BEM and Sass
There’s been a fair bit of discussion in front-end circles recently about CSS architecture. Methodologies such as OOCSS, BEM, SMACSS and various other esoteric acronyms have provided developers with new techniques for building maintainable, scalable front-ends. Proponents including Harry Roberts, Nicole Sullivan and Nicholas Gallagher have demonstrated why we should rethink years of front-end “best-practice”—it simply wasn’t working.
In her talk Our (CSS) Best Practices Are Killing Us, Nicole Sullivan makes a compelling case for revising much of what was previously considered the “right” way of doing things. An important revision, she argues, concerns the use of classes as styling hooks—specifically that we have neglecting them under the guise of avoiding so-called “classitis”.
Separation of Concerns
This has lead to developers everywhere attempting to remove all “presentational” information from their markup. Although this still has some merit (adding a class of ".red" to an element is still going to end badly in many cases)—we were taking it too far. For further reading regarding HTML and semantics, I highly recommend reading Nicholas Gallagher’s article About HTML Semantics and Front-end Architecture.
Object Oriented CSS (OOCSS)
Although OOCSS is a distinct system, it’s also a useful umbrella term for BEM, SMACSS and any other method that abstracts CSS into reusable modules. OOCSS attempts to rationalise the relationship between markup and style by abstracting structure and style into patterns or objects. Liberal use of classes as hooks for this styling is key.
Perhaps the most famous example of OOCSS is Nicole Sullivan’s “media object”. The premise is simple—the pattern of having an image with a title and some copy besides it is so commonplace that it makes sense to create a single system for dealing with it. Whereas previously developers might have recreated this simple CSS several times in various places in a stylesheet, by using the media object we can write the CSS once and then just apply the relevant classes to the markup.
BEM (Block, Element, Modifier)
Originally developed by Yandex, BEM has emerged as a methodology for front-end development that places convention, scalability and code reuse as the main principles of development. At its core, BEM consists of two principles:
- Abstraction of markup in to “blocks”, “elements” and “modifiers” to represent an object.
- The use of a naming convention to describe the above in a way that is meaningful and predictable.
Put simply, BEM is merely a convention used for describing elements on a page in terms of its components. The naming convention is as follows:For a more detailed introduction to BEM syntax, I recommend reading this introduction by Harry Roberts.
In practise, an example of this could be a navigation menu which consists of a block (.nav), elements (.nav__item) and possibly a modifier (more on this later):
Pretty simple so far. Let’s look at how using a modifier allows us to re-use the style from above but for a slightly different layout:
As you can see, the modifier augments the existing pattern in to something slightly different—in our case a stacked navigation. This is not to say that this isn’t possible without using BEM, it's just a simple demonstration of the principle.
My Health Skills
When the brief for arrived, it seemed like a perfect project to practise our BEM chops—it’s modular in nature and has the potential to scale far beyond the initial scope. Having dabbled with BEM on a couple of projects previously, it was time to really see what the system could offer.
Perhaps the biggest challenge with BEM is spotting patterns that can be BEM-ified in the first place. As BEM (and OOCSS) rely on defining what an object is as opposed to what it looks like or what content it contains, it requires a degree of higher-level, abstract thought which can be quite challenging. Furthermore, sometimes you don't notice a pattern until it’s been used several times and the correlation between things becomes clear—by which time it can be too late.
However, working on My Health Skills it became clear pretty early on that one pattern was particularly prevalent. Lists of stuff:
From the news feed on the homepage to the admin UI in the backend, a common pattern of lists of items separated with a line is used throughout. Awesome, I thought—this is an ideal opportunity to get my BEM on. You can imagine the excitement.
Thus, the “.item-list” block was born, along with its siblings “.item-list__header”,”.item-list__body” and all the little “.item”s:
Now, I know what you’re thinking—surely “.item” is an element of the block “item-list” and so should be named “.item-list__item”. This would definitely work but I knew that items themselves were going to become a block (as they have several elements and modifiers) so it seemed simpler to remove them from their relationship with “item-list”—separation of concerns in action.
So here we have the markup for a simple “.item-list”:
And the styling:
Another point that could be raised here is that HTML already has a concept of “lists” that isn’t being used, our friends the unordered (<ul>) and ordered (<ol>) lists. Again, this is a matter of separation of concerns: using these elements would tie the styling to the markup and make it inherently less re-usable. An example of how more “semantic” markup would achieve the same thing:
As you can see, this ties the styling completely to the markup. If we, for example, wanted to employ a (<ul>) for the markup instead, we would have to add an additional rule to the CSS:
Although this is by no means a disaster, it doesn’t scale at all—the more you use this pattern with increasingly diverse markup, the more complex the CSS will become. It’s perhaps worth noting, however that BEM doesn’t uniquely solve this problem—it’s just a good method of doing so.
The real power of BEM becomes apparent when you start to mix objects together so that an element on the page derives style from two or more blocks. For example, our “item-list” is actually composed of both lists and a “section”—another block used on the site. A “section” block is composed of a header, title and body:
Here, the “section” block gives an element the header and title styling, whereas the “item-list” block styles the content. Mixing these blocks together is done via SASS’ @extend directive. For the uninitiated, this allows one rule to inherit properties from another like so:
An alternative approach to this would be simply to add both classes to the HTML—both methods have their advantages and disadvantages. In retrospect, I now prefer the latter “multi-class” approach as it provides better encapsulation of styles. For further reading, I recommend this article in the “for” using @extend camp and this post which is firmly against it.
Nearly a year on from building My Health Skills and having employed BEM to various degrees in numerous projects, I've learned a lot about this methodology. If I were to refactor this now, I would completely separate the "section" and "item-list" blocks, dropping the use of @extend and letting the markup do the work. This is how I would approach it now:
This would remove any concept of a "header" from the "item-list" (it was never used separately from a section anyway) encapsulating the "item-list" away on its own for better separation of concerns.
BEM has become pretty much the defacto methodology for building websites here at Bluegg, enabling us to create sites that are modular, easy to maintain and scalable—what's not to like?
If you have any experiences or comments you'd like to share, please Tweet us!