Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Практика: переводим компонент на БЭМ

Соберём всё, что было в главе, на одном примере. Рефакторинг — изменение кода без изменения его поведения: страница выглядит так же, но код становится понятнее. Возьмём карточку товара, которую писали «как получится», и переведём её на БЭМ.

Исходный код

Вот карточка в том виде, в каком она часто встречается в старых проектах:

<style>
  #catalog div { padding: 12px; border: 1px solid silver; border-radius: 8px; max-width: 240px; margin-bottom: 8px; }
  #catalog div h3 { margin: 0 0 6px; font-size: 18px; }
  #catalog div span { color: seagreen; font-weight: bold; }
  #catalog div button { margin-top: 8px; padding: 6px 12px; border: none; border-radius: 6px; background: seagreen; color: white; }
  .sale { border-color: crimson !important; }
  .sale span { color: crimson; }
</style>
 
<section id="catalog">
  <div>
    <h3>Рюкзак</h3>
    <span>40 €</span><br>
    <button>Купить</button>
  </div>
  <div class="sale">
    <h3>Палатка</h3>
    <span>72 €</span><br>
    <button>Купить</button>
  </div>
</section>

Обратите внимание: у второй карточки рамка красная, а цена осталась зелёной — правило .sale span проиграло селектору с id.

Что здесь не так

  • Селекторы завязаны на id catalog: вне каталога карточку не показать.
  • Стили привязаны к тегам: замените <h3> на <h2> — оформление пропадёт.
  • #catalog div задевает любой <div>, который появится внутри карточки.
  • Модификатор держится на !important, и всё равно перекрасил не всё.

Шаг 1: находим блоки

Сначала решаем, какие части самостоятельны. Карточка — блок product. Кнопка встречается по всему сайту — отдельный блок button. Её место в карточке задаст элемент через микс.

Шаг 2: элементы и модификаторы

БылоСталоЧто это
#catalog div.productблок
#catalog div h3.product__titleэлемент
#catalog div span.product__priceэлемент
#catalog div button.button и .product__buyблок и элемент (микс)
.sale.product--saleмодификатор

<br> больше не нужен: цене достаточно display: block.

Результат

<style>
  .button { padding: 6px 12px; border: none; border-radius: 6px; background: seagreen; color: white; }
 
  .product { padding: 12px; border: 1px solid silver; border-radius: 8px; max-width: 240px; margin-bottom: 8px; }
  .product--sale { border-color: crimson; }
  .product__title { margin: 0 0 6px; font-size: 18px; }
  .product__price { display: block; color: seagreen; font-weight: bold; }
  .product--sale .product__price { color: crimson; }
  .product__buy { margin-top: 8px; }
</style>
 
<section>
  <div class="product">
    <h3 class="product__title">Рюкзак</h3>
    <span class="product__price">40 €</span>
    <button class="button product__buy">Купить</button>
  </div>
  <div class="product product--sale">
    <h3 class="product__title">Палатка</h3>
    <span class="product__price">72 €</span>
    <button class="button product__buy">Купить</button>
  </div>
</section>

Карточки выглядят как раньше, но теперь цена в акционной карточке действительно красная. В коде нет ни id, ни !important, а карточку можно поставить в любое место сайта.

Частая ошибка

Переименовать классы, но оставить вложенные селекторы:

.catalog .product .product__title { margin: 0 0 6px; }
.catalog .product .product__price { color: seagreen; }

Имена стали «бэмными», а специфичность осталась высокой, и карточка по-прежнему работает только внутри .catalog. Проверяйте результат рефакторинга: почти каждый селектор должен состоять из одного класса.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.