As a development concept becomes popular, it is common to witness programmers forking it to fit various workflows and habits. This is resulting in a very fragmented landscape of implementations. It is happening to BEM at this very moment, and I myself have experimented with multiple flavors of it in the past few months.
This blog post has nothing to do with E. L. James’ book Fifty Shades of Grey, but I thought it would be a pretty catchy title. Sorry, folks: no erotic content here (although some developers might find CSS code quite sexy when written with the BEM methodology).
Image may be NSFW.
Clik here to view.
BEM (for Block-Element-Modifier) is a more and more commonly used approach to architect our CSS. If you haven’t heard of it yet, I distilled some information about this concept in a previous blog: Please Respect the Global CSS Namespace (you’ll find plenty of resources about BEM at the bottom of this previous post).
I have had the chance to experiment with it for the last 6 months on sizable projects and I came across many different ways of implementing it.
Note that “BEM” also references to a whole way of building your front-end with CSS, JavaScript and BEMHTML using the BEM Tools. I will not cover that part and focus on how to apply the methodology to our CSS.
Building a Navigation Menu With BEM
One of the most noticeable upsides of applying BEM in our code is that reading the CSS (without knowing what the HTML looks like) makes much more sense than with any other technique. Let’s say we’d like to build a simple navigation menu. The way BEM decomposes a selector name into easily identifiable parts goes as follows:
- Block (e.g.:
navigation
) - Element (e.g.:
item
) - Modifier (e.g.:
active
)
One of the constructs useful with BEM is the Completely Independent Block (CIB): a self-sufficient module that should be portable in as many contexts as possible, with its own set of classes. BEM makes it easy to decompose a component into multiple parts, as when reading this code you’ll know exactly what is supposed to be going on:
.navigation {} .navigation .item {} .navigation .item.active {}
Simple! But in this code lies a massive problem: children .item
elements will inherit .navigation .item
styles. To put it simply: if we nest a sub-navigation in our navigation, then the .subnavigation .item
elements inherit styles from .navigation .item
.
A quick fix would be to use a child selector in our CSS:
.navigation {} .navigation > .item {} .navigation > .item.active {}
Great! Using the above solution, styles will only apply on .item
elements if they are directly nested in .navigation
(and not bleed on .subnavigation .item
, for example). But we now rely very heavily on a particular DOM structure, which makes our code very fragile and not really prone to evolve. Not so great, then. Also, .active
is a pretty common class that involves many risks of collision.
BEM will help us solving both those issues by using low-level identifiers, while avoiding any risk of collision with other UI components:
.navigation {} .navigation__item {} .navigation__item--active {}
This notation makes it quite obvious as of how elements are related to each other. It is very clear to what the HTML structure will look like and at the same time, it gives quite a lot of HTML structure and semantic freedom. The implementation could have .navigation__item
as a direct children of .navigation
, but this is not mandatory. Also, if we nest a subnavigation component in there, we could name its items .subnavigation__item
. Those won’t be affected by the styles in .navigation__item
(solving the cascade problem).
One Concept, Multiple Implementations
BEM is mainly a concept, and its inventors (Yandex) do not try to enforce any specific implementation, notation nor file naming conventions to the developers. In fact, the word is: please do what works for you.
Developers heard the Yandex guys and came up with multiple ways of applying this concept within their CSS. Let’s go through the most popular notations and see how we got there.
Underscores and Meaningful Dashes
The first attempt to reach a BEM-like CSS approach was documented by Nicolas Gallager in his blog “About HTML semantics and front-end architecture”, and thoroughly described in Harry Robert’s blog: MindBEMding – getting your head ’round BEM syntax (in which he tries to sound cool).
It goes something like this:
component-name component-name--modifier-name component-name__sub-object component-name__sub-object--modifier-name
It is really ugly, but when you get your head around how this notation works, it’s a real breeze.
I have started implementing it on the BBC Responsive News website and it looks like the Guardian is doing the same on their Responsive Website. I also implemented this notation in parts of the application when redesigning the platform I’m working for — and despite being ugly, it has always worked really well.
Montage goes CamelCase
In the Montage HTML5 framework, a recent discussion lead to some interesting naming conventions.
“Class names follow a org-Component
and org-Component-childElement
pattern. So for the progress bar it would be: montage-Progress
and montage-Progress-bar
. (…) If a class name represents a state or a variation, double dash is used.”
org-ComponentName org-ComponentName--modifiername org-ComponentName-subObject org-ComponentName-subObject--modifiername
The funny thing is that Montage extended the concept by representing a child of a child via the classname, so we could have a .org-ComponentName-subObject-subChild
identifier.
I personnaly find this notation much more pleasant than the first one. Nicolas Gallagher is now using it in his Suit CSS toolset.
For Google Closure
I work on a product we build using Google Closure. To try and match the JavaScript developers habits, we wanted to have a modifier name that matched the framework naming conventions.
What does Google Closure do when it comes to states? In Google Closure, the mouseover
state is an event of the MOUSEOVER
type. This helped defining our modifier naming convention: all caps! In our codebase, modifiers will be expressed as class-MODIFIER
.
Outside of that small variation, we took a very similar approach to the Montage notation:
prefix-ComponentName prefix-ComponentName-MODIFIERNAME prefix-ComponentName-subObject prefix-ComponentName-subObject-MODIFIERNAME
What does prefix
stand for, you ask? As an additional layer of clarity, we started prefixing our class names like this:
p-
Page specific (class applied on the body element), very useful for static pages where maintainability is not at stake — should be avoided in the application itself (e.g.:p-Homepage
).l-
Layout, columning, wrappers and containers… (e.g.:l-Masthead
,l-Footer
)c-
For components (e.g.:c-Dropdown
,c-Button
…).u-
Utility classes — will probably never change, should never be overridden anywhere else in our code (e.g.:u-textCenter
,u-clearfix
…).js-
Hooks for JavaScript: should never appear in the CSS itself.
With these very descriptive naming conventions (inspired from Jonathan Snook’s SMACSS), we believe we will achieve a much more robust architecture, hopefully less prone to errors from developers messing with the cascade in unexpected ways. Time will tell, I guess.
It’s up to You, Really
If you want to try BEM tomorrow in your project, what naming convention should you adopt? It’s up to you, really.
To be honest, I’ve rarely seen (if present at all) the same naming conventions between two projects, but I’ve even seen a lot of projects with multiple naming conventions in the same codebase (you could tell when the code had been produced by looking at how the class were named). Naming can easily become a bloody free for all — be aware of this and make time for some housekeeping in your code to make sure there is at least some sort of consistency across the whole project.
What about you, do you use BEM (or a BEM-flavored notation)? If so, what is your preferred coding and naming style?