Malax Malax - 1 month ago 13
CSS Question

BEM: What are modifiers allowed to modify?

Let's say I have the following CSS for a generic list component, using BEM and SCSS:

.list {
&__item {
&:not(:last-child) {
margin-right: .3em;
}
}
}


I want to add a modifier that can make the list vertical, like so:

.list--vertical {
display: flex;
flex-direction: column;
}


My problem arises when I think about the margin for list__item elements. For vertical lists, I want my margin on the bottom, not right of each item. If I understood BEM correctly, I cannot modify the style of list__item based on the modifer of list, is that correct?

To be more precise, this is what I want to do:

.list--vertical {
display: flex;
flex-direction: column;

.list__item {
&:not(:last-child) {
margin-bottom: .3em;
margin-right: 0;
}
}
}


What is the accepted way of dealing with this using BEM? Another modifier for list__item that handles the margin? Another block entirely for vertical lists?

Answer

What is the accepted way of dealing with this using BEM?

Depends on what version of BEM you're using. I use a variant of the pre-spec concept of BEM, which means that you'll have different answers if you follow bem.info.


Modifiers should be attached to the element they modify. Modifying a block, however, allows the modifier to be inherited by child elements:

<div class="foo foo--example">
  <div class="foo__bar foo--example__bar">...</div>
<div>

This gets messy when child elements have modifiers as well:

<div class="foo foo--example">
  <div class="
    foo__bar
    foo--example__bar
    foo__bar--another-example
    foo--example__bar--another-example">...</div>
<div>

This form of BEM syntax is quite verbose. It's best used on generated code.


I use LESS for CSS preprocessing, so my BEM code often looks like:

.foo {
  ...

  &__bar {
    ...
  }
}

With modifiers it becomes:

.foo {
  ...

  &__bar {
    ...
  }

  &--example {
    ...

    &__bar {
      ...
    }
  }
}

This enforces that the cascade is in the proper order and that all selectors continue to have exactly one class.

Comments