Инструменты пользователя

Инструменты сайта


web_designe:razmetka_stranicy:behm

Как писать классы по БЭМ?

БЭМ расшифровывается как «Блок Элемент Модификатор». На самом деле, это целый стэк технологий, из которого мы воспользуемся только соглашением по именованию классов.
Почему БЭМ?
  • БЭМ позволяет создавать абсолютно независимые блоки. Блоки и элементы получают уникальные имена, так что стили для одного элемента ничего не поломают в другом.
  • БЭМ помогает легко придумывать любое количество классов, не повторяющихся между собой.
  • БЭМ помогает писать самодокументирующийся код, в классе любого элемента содержится информация о нём.

Подробнее можно почитать в разделах Быстрый старт и Часто задаваемые вопросы на сайте bem.info.

Ниже показаны примеры кода.

1.Простой пример: Блок + Элемент

Допустим, у вас есть блок с заголовком, текстом и кнопкой внутри, например, это всплывающее окно — попап. Разметка:

    <div>
      <h3>Заголовок</h3>
      <div>Текст</div>
      <button>Кнопка</button>
    </div>

Добавляем класс содержащий назначение элемента: .popup:

    <div class="popup">
      <h3>Заголовок</h3>
      <div>Текст</div>
      <button>Кнопка</button>
    </div>

Теперь попробуем добавить классы вложенным элементам:

    <div class="popup">
      <h3 class="title">Заголовок</h3>
      <div class="text">Текст</div>
      <button class="button">Кнопка</button>
    </div>

Классы удобные, но не уникальные. Если на странице будут ещё элементы с классами .title и .text, их стили могут затронуть элементы в попапе. Селектор типа .popup .title может в будущем создать проблемы со специфичностью. Можно придумать другие классы, но чем больше похожих по смыслу элементов, тем сложнее придумывать новые классы.

А теперь применим БЭМ-нотацию: каждому элементу внутри блока добавим префикс с классом родителя, например, для заголовка это будет popup__title:

    <div class="popup">
      <h3 class="popup__title">Заголовок</h3>
      <div class="popup__text">Текст</div>
      <button class="popup__button">Кнопка</button>
    </div>

Теперь эти классы легко решают сразу две задачи: во-первых, благодаря уникальным классам стили для них никогда не пересекутся с другими подобными элементами на странице, а во-вторых, по таким классам сразу видно, что это элементы блока .popup.

2.Пример посложнее: Блок + Элемент + Модификатор

Для примера возьмём сервисное сообщение на сайте. Обычно такие сообщения бывают разных видов, например, сообщение об успешном завершении действия или об ошибке.

    <div class="message">
      <h3 class="message__title">Заголовок сообщения</h3>
      <div class="message__text">Текст сообщения</div>
    </div>

Логично использовать одну и ту же разметку, но с разными цветовыми темами. Именно здесь очень пригодятся модификаторы.

    <div class="message message--success">
      <h3 class="message__title">Заголовок сообщения</h3>
      <div class="message__text">Текст сообщения</div>
    </div>
 
    <div class="message message--error">
      <h3 class="message__title">Заголовок сообщения</h3>
      <div class="message__text">Текст сообщения</div>
    </div>

Обоим элементам можно добавить одинаковые стили используя общий класс .message и так же легко можно добавить отдельные стили для каждого из них, используя уникальный класс с модификатором:

    .message {
      border: 1px solid gray;
    }
      .message--success {
        border-color: green;
      }
 
      .message--error {
        border-color: red;
      }

Оба сообщения будут иметь рамку толщиной один пиксель, но для сообщения об успешной операции она будет зелёной, а для сообщения об ошибке — красной.

3.Ещё сложнее: что делать, если хочется сделать элемент элемента?

Например, на странице есть блок новостей:

    <div class="news">
        <h3>Новости</h3>
 
        <ul>
          <li><!-- новость --></li>
          <li><!-- новость --></li>
        </ul>
    </div>

Заголовок блока логично получает класс .news__title, список — .news__list, а отдельная новость — .news__item:

    <div class="news">
        <h3 class="news__title">Новости</h3>
 
        <ul class="news__list">
          <li class="news__item"><!-- новость --></li>
          <li class="news__item"><!-- новость --></li>
        </ul>
    </div>

Тут никаких проблем возникнуть не должно. Теперь добавим разметку отдельной новости:

    <div class="news">
        <h3 class="news__title">Новости</h3>
 
        <ul class="news__list">
          <li class="news__item">
            <h4>Заголовок новости</h4>
            <p>Текст новости</p>
          </li>
          <li class="news__item"><!-- новость --></li>
        </ul>
    </div>

Нам нужно добавить класс заголовку новости. Первым делом приходит в голову .news__title, но такой класс уже занят. Предположим, что второй элемент будет не .title, а .subject, тогда в CSS получается такое:

    .news__title { ... }
    .news__subject { ... }

Без дополнительных комментариев будет совершенно невозможно понять какой из них является заголовком всего блока, а какой — отдельной новости. Не пойдёт.

Следующий вариант — .news__item__title, но в БЭМ нельзя создавать элемент элемента, и это понятно, потому что получается каша. Ещё вариант: .news__item-title — тоже не годится, потому что может быть неочевидным как title соотносится с item. Как же быть?

Решение простое: на уровне элемента .news__item можно объявить новый блок (например, .news-item), и строить вложенные классы уже от него. Да, это не самостоятельный переиспользуемый блок, здесь объявление блока нужно только для того, чтобы разгрузить селекторы. Что получается:

    <div class="news">
        <h3 class="news__title">Новости</h3>
 
        <ul class="news__list">
          <li class="news__item news-item">
            <h4 class="news-item__title">Заголовок новости</h4>
            <p class="news-item__text">Текст новости</p>
          </li>
          <li class="news__item"><!-- новость --></li>
        </ul>
    </div>

Проблема решена: нам больше не нужно использовать монструозные классы, при этом класс точно описывает элемент, и в CSS будет сразу понятно какой класс за что отвечает:

    .news__title { ... }
    .news-item__title { ... }

Простой и удобный выход из неудобной ситуации. Больше примеров разметки можно увидеть здесь. Ещё одно хорошее руководство по использованию БЭМ есть здесь.

web_designe/razmetka_stranicy/behm.txt · Последние изменения: 2023/01/12 12:18 (внешнее изменение)