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:
| Class | Responsible for | Example properties |
|---|---|---|
block search-form | appearance and content | display, gap, colors |
element header__search | the place in the parent | margin, 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.