Using LESS to DRY out your BEM-style CSS and increase maintainability

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 block name.

The basic CSS for a BEM model is showcased below:

.block {}
.block-element {}
.block--modifier {}

Explanation:

  • The block represents the main component.
  • The block-element (one hyphen) represents a part (sub-element) of the component.
  • The 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">
    <div class="block-element"></div>
</div>

<div class="block block--modifier">
    <div class="block-element"></div>
</div>

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:

.block {
    &-element {}
    &--modifier {}
}

Explanation: For the -element and --modifier declarations the “&” (current parent selector) will reference the .block name, thus rendering them as .block-element and .block--modifier respectively.

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.:

.myblock {
    &-element {}
    &--modifier {}
}

…which renders into:

.myblock {}
.myblock-element {}
.myblock--modifier {}

There you go: Scalable, DRY and low-maintenance BEM-style CSS!


Notes

Multi-level sub-elements

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.:

HTML

<div class="block">
    <div class="block-element">
        <div class="block-element2">
            <div class="block-element3"></div>
        </div>
    </div>

    <div class="block-element4"></div>
</div>

LESS

.block {
    &-element {}
    &-element2 {}
    &-element3 {}
    &-element4 {}
}

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 level in the LESS, i.e.:

.block {
    &- {
        &element {}
        &-modifier {}
    }
}

or even:

.block {
    &- {
        &element {}

        &- {
            &modifier {}
        }
    }
}

… but maybe that is unnecessarily obsessive compulsive.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s