alexbondarev.com

BEM modifiers

I have written several blogposts on BEM so far. There was a post about blocks and elements, mixins, there was even one on BEM levels. But I haven’t expressed my opinion on modifiers yet which I feel I’m finally beginning to understand. I am not going to describe the BEM modifiers in detail, I guess .logo--halloween speaks for itself and most front-end devs would get the idea of such modifiers. What I’m going to try to do instead is to look at an edge case we face when deciding what CSS selectors to have and we’ll see that modifiers will help us there too.

.header__logo vs. .logo--header

I was asked a question not so long ago.

Would it make sense to use .header__logo for following markup in case when you need to extend .logo styles to fit it with other blocks within .header? Or would you create a modifier for .logo?

Serge Zarouski

It happens so that it’s not one or the other. Sometimes it’s one, sometimes the other, sometimes both. By the end of the article I’ll try to explain when to use .header__logo and when to use a modifier.

I find it good to split a component’s styling into two groups: those that can be reused and those that are specific to its current position (location).

The first group of styles can be located in a block class, ensuring the block is completely independent of the surroundings. So I would do something like this:

.logo {
    //styles that are common for all logos on the page,
    //be it clients logos, testimonials logos or any other elements
    //that will have logo as part of their class attribute.
}

//most likely in another file
.header__logo {
    //styles that are specific to the header logo,
    //like float, margin-top, or position.
}

What is important to note here is that putting float, margin-top and position to the .header__logo selector stops them from being reusable… but what if they need to be? What if we had a logo in the footer, for instance, that so conveniently needs to be floated?

The quickest solution would be to repeat the styles in the .footer__logo selector, which is not DRY at all. A better solution would be to extract the repeating styles into a placeholder selector and @extend it in both places. But what I find an even better solution is to extract the styles into a modifier and apply it in both HTML nodes.

.logo {
    //styles that are common for all logos on the page,
    //be it clients logos, testimonials logos or any other elements
    //that will have logo as part of their class attribute.
}

.logo--shifted {
    //styles that are common for a particular design pattern of a
    //certain block like float, or margin-top
}

//most likely in another file
.header__logo {
    //styles that are specific to the header logo, like position.
}

Having a modifier class has helped us to remain DRY not only in our preprocessor files but also in our CSS, which we too often forget to do.

A note on positional modifiers

I feel guilty I proposed .logo--header as a way to deal with such cases. More than half a year has passed and I feel I was a bit naive, as having such a modifier would naturally prevent a developer from reusing this element in another container without modifying. So right now I would say against naming your modifiers using child-parent relations. .header__logo now feels better for position-dependent styles than .logo--header. Or maybe I need another 8 months or so :)

Summary

If I were to extract some rules out of this post I’d probably think of the following:

  1. Use a modifier if you want to abstract a design pattern of a certain block or element (e.g. .logo--black-n-white). Maybe later this abstraction will become block-independent (e.g. .black-n-white)
  2. Use an element selector for those styles that are block-dependent (or positionally dependent). (e.g. .header__logo would have position: relative;)
  3. Avoid using block-dependent modifiers. (e.g. having .logo--header will prevent the styles from reusing them for the logo in another block, bad naming)