Login with github
Forum /

Is any BEM entity allowed to modify any other entity?

Specifically, is an element allowed to modify another entity?

Consider the following example, where a modifier positions another block - in this case, we have a close block for close gadgets on dialogs etc. and a modal block for modal dialogs:

<div class="modal">
  <header class="modal__header">
     Title goes here...
     <span class="close"></span>
  </header>
  <section class="modal__body">
    Content goes here...
  </section>
</div>

The close block itself doesn't have margin/padding/positioning, because we want it to be reusable in different contexts.

In the context of a modal, the close gadget needs to be positioned properly though, and normally I'd just do this:

.modal__header .close {
  position: absolute;
  right: 7px;
  top: 4px;
}

I've been told this goes against BEM, and instead I should add a modal__close element, and mark it up as:

<div class="modal">
  <header class="modal__header">
     Title goes here...
     <span class="close modal__close"></span>
  </header>
  <section class="modal__body">
    Content goes here...
  </section>
</div>

My argument is that the close modal__close combination is meaningless, because:

  1. The modal__close element doesn't work on it's own
  2. If you forget to add modal__close, the close gadget will break the design.
  3. The close block should always and only occur precisely once in a modal__header.

In other words, the close modal__close combination is meaningless since, in the context of a modal, there is no use-case for either close or modal__close without the other.

I'm struggling to understand precisely what BEM is - if it's a naming convention and a set of patterns, the way I understand patterns (as a programmer) is as language used to describe what you've implemented; but not as decision-making drivers that should dictate what you implement.

In the same sense, I feel that BEM naming is valuable as a convention for describing the logical relationships between CSS classes - and shouldn't be viewed as a set of rules that dictate how you structure your CSS.

In fact, for this modal example, I'd like to go even simpler and drop the modal elements:

<div class="modal">
  <header>
     Title goes here...
     <span class="close modal__close"></span>
  </header>
  <section>
    Content goes here...
  </section>
</div>

And just write CSS like this:

.modal > header {
  ...
}

.modal > section {
  ...
}

Again, my argument is that the immediate header and section elements of a .modal are clearly already elements in the HTML sense, and there is no other use-case for header or section elements as immediately children of a .modal except as the header and body elements of that modal.

Overriding these with a modifier, despite the higher specificity, is literally almost the same thing - e.g. this:

.modal--large > header { ... }

Versus this:

.modal--large .modal--header { ... }

I don't understand how either of these is any better or worse, beside the specificity argument, which seems inconsequential here, since you'll need to specify the modifier and target the header element somehow, for any rule that affects anything below it.

In fact, the first option seems like a generally safer choice in a lot of cases, such as, for example, panels within panels:

<div class="panel panel--red">
  <header>...</header>
  <section>
    Some content here, and another panel:
    <div class="panel">
      ...
    </div>
  </section>
</div>

In this example, I'd like to target .panel--red > section to make it red - and this won't and should not affect the color of the nested panel inside it.

Contrast this with:

<div class="panel panel--red">
  <header class="panel__header">...</header>
  <section class="panel__body">
    Some content here, and another panel:
    <div class="panel">
      ...
    </div>
  </section>
</div>

If you target the panel body with a selector like .panel--red .panel__body to affect the color, this will cascade to any nested panel__body elements and override their default color, which is not what was intended.

Bottom line: should you think for yourself and implement your CSS as needed - or should you apply BEM patterns slavishly and set aside your own judgment?

Do my examples go against BEM in any way?