If writing scalable CSS for your HTML5 projects is of concern to you, chances are that at some point you’ve bumped into the Block, Element, Modifier (or BEM for short) approach. Basically (in my interpretation) what BEM advocates is a model for writing/organizing CSS where:
- Anything that needs to be styled has a class name, i.e. no styling based on element types.
- Classes are independent and defined on the same level, so that no styles are dependent of their ancestry, i.e. no class nesting.
- Related classes are grouped together using a common
The basic CSS for a BEM model is showcased below:
block represents the main component.
block-element (one hyphen) represents a part (sub-element) of the component.
block--modifier (two hyphens) is a modification to the
block, e.g. a different background color, layout etc.
(Note: The source BEM approach referenced in the introduction uses “_” (underscores) as separators, but I use “-” (hyphens/dashes) – it’s just a matter of personal preference.)
An HTML structure for the block could look something like this:
<div class="block block--modifier">
The example shows two versions of the
.block component which both contain a sub-element
.block-element, but the second component also contains a
.block--modifier which could e.g. display it with a different background color. As all CSS classes start with the same
block name it’s easy to see that they are part of the same block.
Now, even though this makes for some pretty understandable and scalable CSS (as blocks and sub-elements will look the same regardless of their context), from a maintainability standpoint, there is a lot of repetition as each style declaration starts with the
block name, i.e. the code is not especially DRY, and e.g. changing your mind about the
block name will require you to update multiple lines of CSS (3 in the basic example above).
(LESS) CSS pre-processing to the rescue
Luckily, if you’re using the LESS CSS pre-processor (and I’m sure that SASS has the equivalent functionality) there’s an easy way for you to organize your source code which will DRY it out and make it a lot more maintainable: LESS gives us the ability to reference the current selector parent using the “&” (ampersand) character. This means that by using LESS we can reduce our LESS/CSS code to this:
Explanation: For the
--modifier declarations the “&” (current parent selector) will reference the
.block name, thus rendering them as
Implementing the above approach means that when you want to change the
block name, to e.g.
myblock, you only need to change the initial block name (i.e. the first line) and LESS will take care of the rest, i.e.:
…which renders into:
There you go: Scalable, DRY and low-maintenance BEM-style CSS!
Many times your blocks will probably contain multiple levels of nested sub-elements, but you should still keep all of the classes directly related to the main
block to ensure that the individual sub-elements parts are as loosely coupled as possible, e.g.:
Further DRY’ing your LESS
If you’re really (as in really, really) DRY, you will have noticed that there are redundant hyphens/dashes all over the examples, so to get rid of these you can insert additional levels in the LESS code, i.e.:
… which would leave you with no redundancy in the structure, but perhaps this is taking LESS to extremes. The main priority is that you adapt the functionality to your current situation and do what makes most sense to you – perhaps even on a file-to-file basis.