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)
  • Well summarized, thank you for the article. I share your point of view.

  • Freddy Hidalgo-Monchez

    What I find very confusing with BEM is how a block like the class logo can be both an element (header__logo) and a block (logo). The logo can be an independent entity that is extended by other blocks like the header or footer so I grasp why you wrote it as a modifier in the last post “logo–header”. But I understand why that makes it hard to reuse. If blocks can be elements and vice versa then how do you organize them in a spec sheet or project folders (blocks/__elements/__modifiers)? Is there another way to make the distinction then having to write class=”logo header__logo” to know that logo is both in this case? Great articles btw! I feel like there aren’t enough discussions on this part of BEM…

    • Hey Freddy, that’s a good question. Yes, you are right that one element can have a collection of classes that may be of all the 3 BEM types. Having multiple types on a node makes it a BEM mixin (I wrote once about them too).

      As far as the folder structure goes, I tend to organize my files according to BEM blocks without having inner directories for elements.

      For example, I’d have an SCSS file called header.scss where I’d put .header__logo {} styles. Using a newer version of Sass allows me to nest the elements visually without nesting them in CSS. So a code like this (.header{ color: red; &__logo { float: left; } }) will be transformed into .header { color: red; } .header__logo { float: left }. Which I find nice. Note however that I do not usually @extend silent selectors, so I would still have a logo.scss file to store the reusable parts. The primary reason for this is to try and keep CSS DRY. Although I’ve met several opinions from notable frontenders that keeping CSS DRY is no longer a big issue, I still think it’s worth doing. The order in which I put the classes in is like this: <a class="header__logo logo logo--shifted">. I find it good to first show it has got some relations to the parent.

      Also I’ve met opinions voting against nesting the element selectors as it will prevent certain text editors from jumping directly into the file when clicking the classname in HTML. I happen to not use similar features and know directly if I see .footer__nav I go (or search for) footer.scss. There may come a moment when I try to summarize my thoughts on the BEM architecture that I use, but the more I use it the more I learn too :)

      • Freddy Hidalgo-Monchez

        Completely agree about showing the relationship. That’s what I’m doing now and it looks more clear. I’m also following a similar folder structure. Thanks for clearing that up, Alex!