БЭМ: миксы
В уроке о блоках мы договорились: блок не задаёт себе внешние отступы и положение. Но кто-то же должен поставить поиск в правый угол шапки! Для этого в БЭМ есть микс — несколько сущностей БЭМ на одном теге.
Что такое микс
Микс — это просто несколько классов БЭМ из разных блоков в одном атрибуте class. Самый частый случай: тег одновременно блок сам по себе и элемент родительского блока:
<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">Магазин</span>
<form class="search-form header__search">
<input class="search-form__input" placeholder="Поиск">
<button class="search-form__button">Найти</button>
</form>
</header>Тег <form> — это блок search-form и элемент header__search сразу. Форма прижата вправо, хотя сама об этом ничего не знает.
Кто за что отвечает
Классы в миксе делят обязанности:
| Класс | Отвечает за | Пример свойств |
|---|---|---|
блок search-form | внешний вид и содержимое | display, gap, цвета |
элемент header__search | место в родителе | margin, width, grid-area |
Благодаря этому одну и ту же форму поиска можно поставить в шапку, в подвал и в мобильное меню — у каждого места будет свой элемент с нужным положением.
Один блок в разных местах
Покажем это на кнопке. Блок button одинаков, а положение задают элементы разных родителей:
<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">
Рюкзак, 40 €
<button class="button card__buy">Купить</button>
</div>
<div class="dialog">
Удалить товар?
<button class="button dialog__ok">Да</button>
</div>В карточке кнопка растянулась на всю ширину, в диалоге прижалась вправо, а оформление у неё одно.
Микс с модификатором
В миксе можно использовать и модификаторы любой из сущностей. Например, class="button button--primary card__buy" — кнопка основного цвета, которая занимает своё место в карточке. Классов становится больше, но каждый отвечает за одну вещь.
Частая ошибка
Менять блок через каскад родителя вместо микса:
<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">
Палатка, 90 €
<button class="button button--wide-off">Должна быть узкой</button>
</div>Селектор .card .button сильнее одиночного модификатора, и кнопка осталась широкой — снова война специфичности. С миксом card__buy все селекторы состоят из одного класса, и такого спора не возникает.