How to modify multiple elements of a block with BEM CSS

2.2k views Asked by At

Let us say I have the following setup,

.block
  .block__header
  .block__content
  .block__footer

Now I want to show an active state of this block. Let us say the block itself gets a green background and element 2 and 3 should get bold text. As I understand the philosophy of BEM, one should not use child selectors in order to keep the specificity as low as possible.

So is this really the way to do it?

.block.block--active
  .block__header
  .block__content.block__content--active
  .block__footer.block__footer--active

Update: and how would I write that solution in SASS (very new to it)? This my setup so far... if I can use nested selectors, what is best practice here?

.block {
  &--active {

  }
  &__header {

  }
  &__content {
    // active modifier of content
    &--active {
      font-weight: bold;
    }
    // would be the same as
    .block--active & {
      font-weight: bold;        
    }
    // but can i reference the active block somehow else in sass? 
    // & is a parent selector but i would need the parent of the parent here...
  }
  &__footer {
    &--active {

    }
  }
}
1

There are 1 answers

0
Paleo On BEST ANSWER

The philosophy of BEM is about to keep blocks context free. The low specificity is just a good practice, not a golden rule. I give three valid solutions below.

If you're sure the block cannot be recursively included in itself, a simple cascade can be used:

.block--active {
    background-color: green;
}
.block--active .block__element-2,
.block--active .block__element-3 {
    font-weight: bold;
}

If the elements are directly located in the block, the children selector is valid:

.block--active {
    background-color: green;
}
.block--active > .block__element-2,
.block--active > .block__element-3 {
    font-weight: bold;
}

Or the flat solution (but not DRY):

.block--active {
    background-color: green;
}
.block__element-2--active,
.block__element-3--active {
    font-weight: bold;
}

With SCSS, there are several ways to write the first solution. Here is the one I use:

.block {
    &--active {
        background-color: green;
    }
    &--active &__element-2,
    &--active &__element-3 {
        font-weight: bold;
    }
}

See another solution here.