dr.Brain

doctor Brain

мир глазами веб-разработчика

БЭМ: Как сделать жизнь разработчика чуть лучше

БЭМ компонентный подход (Блок - Элемент - Модификатор), ставший мировым стандартом в CSS, позволяет разрабатывать масштабируемые интерфейсы легкие в чтении и понимании

dr.Brain

время чтения 3 мин.

Photo by Magdalena Smolnicka on Unsplash

В основе подхода БЭМ лежит принцип разделения компонента на независимые блоки. Он позволяет легко и быстро разрабатывать интерфейсы любой сложности и повторно использовать существующий код, не прибегая к ненужному копированию.

Почему БЭМ?

У данного подхода есть, как минимум два преимущества:

  1. использование БЭМ не вызывает затруднений,
  2. созданные масштабируемые структуры легки в понимании.

Что такое БЭМ?

Имена классов при использовании БЭМ состоят из трех частей (Блок - Элемент - Модификатор):

[block]__[element]--[modifier]
  1. Блок: самый внешний родительский элемент, в HTML это класс, определяющий основные функции компонента. Название блока должно определять смысл, а не состояние.
  2. Элемент: в компоненте может быть определен один или несколько элементов. Элементы добавляют блоку новые функции и не используются в отрыве от него. Свойства элемента не заменяют все свойства блока.
  3. Модификатор: блок или элементы может иметь различные варианты, определяемые модификаторами. Модификатор определяет внешний вид, состояние или поведение блока или элемента.

Примеры

Блок без элементов и модификаторов

Самые простые компоненты включают в себя только один класс, который и будет являться блоком

<style>
    .btn{}
</style>

<button class="btn"></button>

Компонент с простым модификатором

Как мы уже знаем, компонент может иметь различные варианты. Вариант может определяться классом модификатора. Модификатор не может существовать сам по себе, без блока. Классы модификаторов предназначены для расширения базовых классов, а не для их замещения.

Вот пример правильного использования класса модификатора:

<!-- Правильно -->
<style>
   .btn {
      display: inline-block;
      color: blue;
   }
   .btn--secondary {
      color: green;
   }
</style>
<button class="btn btn--secondary"></button>

А так делать нельзя:

<!-- Неправильно -->
<style>
   .btn--secondary {
      display: inline-block;
      color: green;
   }
</style>
<button class="btn--secondary"></button>

Компоненты с элементами

Более сложные компоненты имеют вложенные элементы. Название класса каждого дочернего элемента в составе компонента должно начинаться с имени блока. Одной из основных задач БЭМ является сохранение последовательностей. Поэтому корректно именуйте классы элементов. Для вложенных элементов, имеющих CSS свойства, необходимо создавать классы с корректными именами.

Вот пример правильного именования элементов:

<!-- Правильно -->
<style>
   .card{}
   .card__title{}
   .card__description{}
</style>

<div class="card">
   <h1 class="card__title"></h1>
   <p class="card__description"></p>
</div>

А такой подход будет неверным:

<!-- Неправильно -->
<style>
   .card{}
   .card h1{}
   .card p{}
</style>

<div class="card">
   <h1></p>
   <p></p>
</div>

Относительно родительского блока, элементы могут иметь несколько уровней вложенности. В таком случае не пытайтесть создавать многоуровневые имена классов. БЭМ не поддерживает такие многоуровневые структуры. Имя класса, определяющего CSS свойства вложенного элемента, должно содержать только название элемента и родительского блока, независимо от уровне вложенности элементов.

Такой подход будет верным:

<!-- Правильно -->

<style>
   .card{}
   .card__title{}
   .card__description{}
   .card__excerpt{}
   .card__button{}
</style>

<div class="card">
   <h1 class="card__title"></h1>
   <div class="card__description">
      <p class="card__excerpt"></p>
      <button class="card__button"></button>
   </div>
</div>

А такой - нет:

<!-- Неправильно -->

<style>
   .card{}
   .card__title{}
   .card__description{}
   .card__description__excerpt{}
   .card__description__button{}
</style>

<div class="card">
   <h1 class="card__title"></h1>
   <div class="card__description">
      <p class="card__description__excerpt"></p>
      <button class="card__description__button"></button>
   </div>
</div>

Элементы с модификаторами

Иногда необходимо изменить только один элемент в компоненте. В таком случае модификатор необходимо добавить к элементу, а не к блоку:

<style>
   .card{}
   .card__title{}
   .card__title--big{} /* свойства для изменяемого элемента */
   .card__description{}
   .card__excerpt{}
   .card__button{}
</style>

<div class="card">
   <h1 class="card__title card__title--big"></h1>
</div>

Изменения элементов модифицированных блоков

Если Вы преобразуете элементы компонента одинаковым образом, имеет смысл добавить модификатор для блока, а стили элементов изменять вторично уже на основе этого модификатора. Такой подход сделает код более специфичным и понятным, упростит сам процесс модификации родительского блока.

Так будет правильно:

<!-- Правильно -->

<style>
   .card--dark .card__title{}
   .card--dark .card__description{}
</style>

<div class="card card--dark">
   <h1 class="card__title"></h1>
   <p class="card__description"></p>
</div>

А так неправильно:

<!-- Неправильно -->

<style>
   .card__title--dark{}
   .card__description--dark{}
</style>

<div class="card">
   <h1 class="card__title card__title--dark"></h1>
   <p class="card__description card__description--dark"></p>
</div>

Как быть с именами, состоящими из нескольких слов?

Двойное подчеркивание и двойной дефис в БЭМ созданы как раз для этого: они разделяют смысловые структуры компонента:

[block]__[element]--[modifier]

Таким образом, простые одинарные дефисы используются как разделители слов.

Имена классов должны быть понятными и легкочитаемыми. Использование аббревиатура нежелательно, за исключением тех случаев, когда она является общепризнанной.


Дополнительная информация

  1. БЭМ (язык: русский и английский),
  2. getBEM.com (язык: английский),
  3. БЭМ. Технологии Яндекса (язык: русский)

Спасибо за внимание.

Новые публикации

Далее

Категории

О нас

Frontend & Backend. Статьи, обзоры, заметки, код, уроки.