Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

BEM: mixes

In the lesson on blocks we agreed: a block does not set its own outer margins and position. But someone has to put the search in the right corner of the header! For this BEM has the mix — several BEM entities on one tag.

What a mix is

A mix is simply several BEM classes from different blocks in one class attribute. The most common case: a tag is a block in its own right and at the same time an element of its parent block:

<style>
  .header { display: flex; align-items: center; padding: 8px 12px; background: whitesmoke; }
  .header__logo { font-weight: bold; }
  .header__search { margin-left: auto; }
 
  .search-form { display: flex; gap: 4px; }
  .search-form__input { padding: 4px 8px; border: 1px solid silver; border-radius: 4px; }
  .search-form__button { padding: 4px 10px; border: none; border-radius: 4px; background: royalblue; color: white; }
</style>
 
<header class="header">
  <span class="header__logo">Shop</span>
  <form class="search-form header__search">
    <input class="search-form__input" placeholder="Search">
    <button class="search-form__button">Find</button>
  </form>
</header>

The <form> tag is both the search-form block and the header__search element. The form is pushed to the right, although it knows nothing about it.

Who is responsible for what

The classes in a mix split the duties:

ClassResponsible forExample properties
block search-formappearance and contentdisplay, gap, colors
element header__searchthe place in the parentmargin, width, grid-area

Thanks to this, the same search form can be placed in the header, the footer and the mobile menu — each place has its own element with the right position.

One block in different places

Here it is with a button. The button block is the same, and the position is set by elements of different parents:

<style>
  .button { padding: 6px 12px; border: none; border-radius: 6px; background: seagreen; color: white; }
 
  .card { padding: 12px; border: 1px solid silver; border-radius: 8px; max-width: 240px; margin-bottom: 8px; }
  .card__buy { display: block; width: 100%; margin-top: 8px; }
 
  .dialog { display: flex; padding: 12px; background: whitesmoke; }
  .dialog__ok { margin-left: auto; }
</style>
 
<div class="card">
  Backpack, €40
  <button class="button card__buy">Buy</button>
</div>
<div class="dialog">
  Remove the item?
  <button class="button dialog__ok">Yes</button>
</div>

In the card the button stretches to the full width, in the dialog it is pushed to the right, but its styling is the same.

A mix with a modifier

A mix can also use modifiers of any of its entities. For example, class="button button--primary card__buy" is a primary-colored button that takes its place in the card. There are more classes, but each one is responsible for one thing.

Common mistake

Changing a block through the parent's cascade instead of a mix:

<style>
  .button { padding: 6px 12px; border: none; border-radius: 6px; background: seagreen; color: white; }
  .card .button { display: block; width: 100%; margin-top: 8px; }
  .button--wide-off { display: inline-block; width: auto; }
</style>
 
<div class="card">
  Tent, €90
  <button class="button button--wide-off">Should be narrow</button>
</div>

The .card .button selector is stronger than a single modifier, so the button stayed wide — a specificity war again. With a card__buy mix all selectors are a single class, and this argument never happens.

Thanks for reading!

Donate to the site — we work hard for you.