БЭМ для начинающих: зачем нужен БЭМ

Опубликовано: 2022-03-10
Краткое резюме ↬ Изоляция стилей CSS — наиболее частая отправная точка использования БЭМ. Но это меньшее, что может вам дать БЭМ. БЭМ привносит системный подход в ваш проект и не дает ему запутаться.

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

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

Большой БЭМ состоит из методологии , технологий , библиотек и инструментов . В этой статье мы подробнее поговорим о самой методологии, потому что это концентрированный опыт огромного количества разработчиков и она привносит системный подход в любой проект.

Чтобы показать вам некоторые практические примеры БЭМ, мы коснемся БЭМ-технологий и полностью пропустим библиотеки и инструменты.

От теории к практике:

  • Основные причины, по которым мы не используем никакие селекторы, кроме классов
  • Основы БЭМ
    • Блоки и элементы
    • Модификаторы и миксы
    • Блоки в файловой структуре
  • Неочевидные преимущества методологии
  • Практический пример: БЭМ подходит не только для CSS
  • БЭМ — это настраиваемая система

Итак, БЭМ — герой или злодей? Тебе решать! Но сначала прочитайте статью.

БЭМ как логотип Бэтмена
БЭМБэтмен
Еще после прыжка! Продолжить чтение ниже ↓

Основные причины, по которым мы не используем никакие селекторы, кроме классов

Одно из основных правил методологии БЭМ — использовать только селекторы классов. В этом разделе мы объясним, почему.

  • Почему мы не используем идентификаторы?
  • Почему мы не используем селекторы тегов?
  • Почему бы нам не использовать универсальный селектор?
  • Почему бы нам не использовать сброс CSS?
  • Почему мы не используем вложенные селекторы?
  • Почему бы нам не объединить тег и класс в селекторе?
  • Почему бы нам не использовать комбинированные селекторы?
  • Почему мы не используем селекторы атрибутов?

Мы не используем идентификаторы (селекторы идентификаторов)

ID обеспечивает уникальное имя для элемента HTML. Если имя уникально, вы не сможете повторно использовать его в интерфейсе. Это предотвращает повторное использование кода.

Распространенные заблуждения

  1. Идентификаторы необходимы для использования JavaScript.
    Современные браузеры могут работать как с идентификаторами, так и с классами. Любой тип селектора обрабатывается в браузере с одинаковой скоростью.
  2. Идентификаторы используются с <label> .
    Если вы поместите <label> внутрь элемента управления, ему не нужен идентификатор. Вместо <input id="ID"><label for="ID">Text</label> просто используйте <label><input type="...">Text</label> .

Мы не используем селекторы тегов

Разметка HTML-страницы нестабильна: новый дизайн может изменить вложенность разделов, уровни заголовков (например, с <h1> на <h3> ) или превратить абзац <p> в <div> . Любое из этих изменений нарушит стили, написанные для тегов. Даже если дизайн не меняется, набор тегов ограничен. Чтобы использовать существующий макет в другом проекте, вам нужно решить конфликты между стилями, написанными для одних и тех же тегов.

Расширенный набор семантических тегов также не может удовлетворить все потребности макета.

Например, когда заголовок страницы содержит логотип. Щелчок по логотипу открывает главную страницу сайта ( index ). Вы можете пометить его тегами, используя <img> для изображения и тег <a> для ссылки.

 <header> <a href="/"> <img src="img.logo.png" alt="Logo"> </a> </header>

Чтобы отличить ссылку с логотипом от обычной ссылки в тексте, нужны дополнительные стили. Теперь удалите подчеркивание и синий цвет ссылки на логотип:

 header a { ... }

Ссылку на логотип не нужно показывать на главной странице, поэтому измените разметку индексной страницы:

 <header> <!-- the <a> tag is replaced with <span> --> <span> <img src="img.logo.png" alt="Logo"> </span> </header>

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

 header a, header span { ... }

На первый взгляд с этим кодом все в порядке, но представьте, если дизайнер уберет логотип из макета. Названия селекторов не помогают понять, какие стили следует удалить из проекта с логотипом. Селектор «header a» не показывает связи между ссылкой и логотипом. Этот селектор может принадлежать ссылке в меню шапки или, например, ссылке на профиль автора. Селектор «header span» может принадлежать любой части заголовка.

Чтобы избежать путаницы, просто используйте селектор класса logo , чтобы написать стили логотипа:

 .logo { ... }

Мы не используем сброс CSS

Сброс CSS — это набор глобальных правил CSS, созданных для всей страницы. Эти стили влияют на все узлы компоновки, нарушают независимость компонентов и затрудняют их повторное использование.

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

Мы не используем универсальный селектор ( * )

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

  • Вы должны дополнительно перенести стили со звездочкой в ​​проект. Но в этом случае универсальный селектор может повлиять на стили в новом проекте.
  • Стили, отмеченные звездочкой, необходимо добавить в переносимый макет.

Кроме того, универсальный селектор может сделать код проекта непредсказуемым. Например, это может повлиять на стили компонентов универсальной библиотеки.

Общие стили не экономят ваше время. Часто разработчики начинают с того, что сбрасывают все поля для компонентов ( * { margin: 0; padding: 0; } ), но потом все равно выставляют их такими же, как в макете (например, margin: 12px; padding: 30px; ).

Мы не используем вложенные селекторы

Вложенные селекторы увеличивают связанность кода и затрудняют его повторное использование.

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

 .button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }

Мы не используем комбинированные селекторы

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

Рассмотрим следующий код:

 <button class="button button_theme_islands">...</button>

Допустим, вы установили правила CSS в селекторе .button.button_theme_islands , чтобы писать меньше. Затем вы добавляете в блок модификатор «active»:

 <button class="button button_theme_islands button_active">...</button>

Селектор .button_active не переопределяет свойства блока, записанные как .button.button_theme_islands , потому что .button.button_theme_islands более конкретен, чем .button_active . Чтобы переопределить его, объедините селектор модификатора блока с селектором .button и объявите его ниже .button.button_theme_islands потому что оба селектора одинаково специфичны:

 .button.button_theme_islands {} .button.button_active {}

Если вы используете простые селекторы классов, у вас не возникнет проблем с переопределением стилей:

 .button_theme_islands {} .button_active {} .button {}

Мы не объединяем тег и класс в селекторе

Объединение тега и класса в одном селекторе (например, button.button ) делает правила CSS более конкретными, поэтому их сложнее переопределить.

Рассмотрим следующий код:

 <button class="button">...</button>

Допустим, вы установили правила CSS в селекторе button.button . Затем вы добавляете active модификатор в блок:

 <button class="button button_active">...</button>

Селектор .button_active не переопределяет свойства блока, записанные как button.button , потому что button.button является более конкретным, чем .button_active . Чтобы сделать его более конкретным, вы должны объединить селектор модификатора блока с тегом button.button_active .

По мере развития проекта у вас могут появиться блоки с input.button , span.button или a.button . В этом случае все модификаторы блока button и все его вложенные элементы потребуют четырех разных объявлений для каждого экземпляра.

Возможные исключения

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

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

 <div class="content"> ... <!-- the user's text --> </div> CSS rules: .content a { ... } .content p { font-family: Arial, sans-serif; text-align: center; }

Мы не используем селекторы атрибутов

Селекторы атрибутов менее информативны, чем селекторы классов. В качестве доказательства рассмотрим пример с формой поиска в шапке:

 <header> <form action="/"> <input name="s"> <input type="submit"> </form> </header>

Попробуйте использовать атрибуты селектора для написания стилей формы:

 header input[type=submit], header input[type=checkbox] { width: auto; margin-right: 20px; } header input[type=checkbox] { margin: 0; }

В этом примере вы не можете точно сказать по имени селектора, что стили принадлежат форме поиска. Использование классов делает его более понятным. Классы не имеют ограничений, которые мешают вам писать четко. Например, вы можете написать это так:

 .form .search { ... }

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

Но вложенные селекторы по-прежнему делают правила CSS более конкретными и не позволяют переносить макет между проектами. Чтобы избавиться от вложенности, используйте принципы БЭМ.

Резюме : class — единственный селектор, позволяющий изолировать стили каждого компонента в проекте; повысить читаемость кода и не ограничивать повторное использование макета.

Изоляция стилей CSS — наиболее частая отправная точка пути БЭМ. Но это меньшее, что может вам дать БЭМ. Чтобы понять, как в БЭМ устроены изолированные независимые компоненты, необходимо изучить основные понятия, т.е. Блок, Элемент, Модификатор и Микс. Давайте сделаем это в следующем разделе.

Основы БЭМ

  • Блоки и элементы
  • Модификаторы и миксы
  • Блоки в файловой структуре

Блок и элементы

Методология БЭМ — это набор универсальных правил, которые можно применять вне зависимости от используемых технологий, таких как CSS, Sass, HTML, JavaScript или React.

БЭМ помогает решать следующие задачи:

  • Повторное использование макета;
  • Безопасно перемещайте фрагменты макета внутри проекта;
  • Перемещайте готовый макет между проектами;
  • Создавать стабильный, предсказуемый и понятный код;
  • Сократите время отладки проекта.

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

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

Чтобы увидеть всю мощь БЭМ-именования, рассмотрим этот пример с формой. По методологии БЭМ форма реализуется с помощью блока form . В HTML имя блока включается в атрибут class :

 <form class="form" action="/">

Все части формы (блок form ), не имеющие смысла сами по себе, считаются ее элементами. Итак, поле поиска ( search ) и кнопка ( submit ) являются элементами блока form . Классы также указывают, что элемент принадлежит блоку:

 <form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

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

Названия селекторов дают понять, что для того, чтобы переместить форму в другой проект, нужно скопировать все ее компоненты:

 .form__search {} .form__submit {}

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

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

Модификаторы и миксы

Официально « М » означает Модификатор, но это также подразумевает еще одно важное понятие в БЭМ: «микс». И модификаторы, и миксы вносят изменения в блок и его элементы. Давайте посмотрим на это поближе.

Модификаторы

Модификатор определяет внешний вид, состояние и поведение блока или элемента. Добавление модификаторов не является обязательным. Модификаторы позволяют комбинировать различные функции блока, так как вы можете использовать любое количество модификаторов. Но блоку или элементу не могут быть присвоены разные значения одного и того же модификатора.

Давайте рассмотрим, как работают модификаторы.

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

 header .form {} footer .form {}

Селектор header .form имеет больший вес, чем селектор form , а это означает, что одно правило переопределяет другое. Но, как мы уже говорили, вложенные селекторы увеличивают связанность кода и затрудняют повторное использование, поэтому этот подход нам не подходит.

В БЭМ можно использовать модификатор для добавления в блок новых стилей:

 <!-- Added the form_type_original modifier--> <form class="form form_type_original" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

Строка <form class="form form_type_original"></form> указывает, что блоку был присвоен модификатор type с original значением. В классической схеме имя модификатора отделяется от имени блока или элемента символом подчеркивания.

Форма может иметь уникальный цвет, размер, тип или тему оформления. Все эти параметры можно задать с помощью модификатора:

 <form class="form form_type_original form_size_m form_theme_forest"> <form class="form form_type_original form_size_m form_theme_forest">

Одна и та же форма может выглядеть по-разному, но оставаться одного размера:

 <form class="form form_type_original form_size_m form_theme_forest"></form> <form class="form form_type_original form_size_m form_theme_sun"></form>

Но селекторы для каждого модификатора по-прежнему будут иметь одинаковый вес:

 .form_type_original {} .form_size_m {} .form_theme_forest {}

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

 .form { /* universal block styles */ } .form_type_original { /* added styles */ }

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

 <form class="form form_type_original"></form>

Вы можете использовать модификаторы для применения универсальных компонентов в очень специфических случаях. Код блока и элемента не меняется. На узле DOM создается необходимая комбинация модификаторов.

Миксы

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

Микс означает, что вы размещаете несколько БЭМ-сущностей (блоков, элементов, модификаторов) на одном DOM-узле. Подобно модификаторам, миксы используются для смены блоков. Давайте рассмотрим несколько примеров, когда вы должны использовать микс.

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

 .form, .search, .register { ... }

Вы можете использовать микс для создания семантически разных блоков для одной и той же формы:

 <form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

Селектор класса .form описывает все стили, которые можно применить к любой форме (заказ, поиск или регистрация):

 .form {}

Теперь из универсальной формы можно сделать форму поиска. Для этого создайте в проекте дополнительный класс search . Этот класс будет отвечать только за поиск. Чтобы объединить стили и поведение классов .form и .search , поместите эти классы на один узел DOM:

 <form class="form search" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

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

Возьмем еще один пример, где меняется семантика компонента. Вот меню навигации в шапке страницы, в котором все записи являются ссылками:

 <nav class="menu"> <a class="link" href=""></a> <a class="link" href=""></a> <a class="link" href=""></a> </nav>

Ссылочный функционал уже реализован в блоке link , но ссылки в меню должны визуально отличаться от ссылок в тексте. Есть несколько способов изменить ссылки меню:

  1. Создайте модификатор входа в меню, который превращает вход в ссылку:
     <nav class="menu"> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> </nav>

    В этом случае для реализации модификатора необходимо скопировать поведение и стили блока link. Это приведет к дублированию кода.
  2. Используйте сочетание универсального блока `link` и элемента `item` блока `menu`:
     <nav class="menu"> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> </nav>

    Сочетая две БЭМ-сущности, вы теперь можете реализовать базовую функциональность ссылок из блока link и дополнительные правила CSS из блока menu и избежать дублирования кода.

Внешняя геометрия и позиционирование: отказ от абстрактных HTML-оболочек

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

Эта задача имеет несколько решений:

  1. Напишите стили с отступами для блока меню:
     .menu { margin-left: 20px; }

    В этом случае блок «меню» уже не является универсальным. Если вам нужно разместить меню в нижнем колонтитуле страницы, вам придется редактировать стили, потому что отступы, вероятно, будут другими.
  2. Создайте модификатор блока меню:
     <div> <ul class="menu menu_type_header"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
     .menu_type_header { margin-left: 20px; } .menu_type_footer { margin-left: 30px; }

    В этом случае проект будет включать в себя два вида меню, хотя это не так. Меню остается прежним.
  3. Определите внешнее позиционирование блока: вложите блок `menu` в абстрактную оболочку (например, блок `wrap`), установив все отступы:
     <div class="wrap"> <ul class="menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>

    Чтобы избежать соблазна создавать модификаторы и изменять стили блока для позиционирования блока на странице, вам нужно понять одну вещь:

    Отступ от родительского блока не является особенностью вложенного блока. Это особенность родительского блока. Он должен знать, что вложенный блок должен иметь отступ от границы на определенное количество пикселей.
  4. Используйте смесь. Информация о расположении вложенного блока содержится в элементах родительского блока. Затем элемент родительского блока смешивается с вложенным блоком. В этом случае вложенный блок не имеет отступов и может быть легко использован повторно в любом месте.

Продолжим наш пример:

 <div> <ul class="menu header__menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>

При этом внешняя геометрия и позиционирование блока menu задаются через элемент header__menu . Блок menu не содержит отступов и может быть легко использован повторно.

Элемент родительского блока (в нашем случае это header__menu ) выполняет задачу блоков-оболочек, отвечающих за внешнее позиционирование блока.

Блоки в файловой структуре

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

Реализация каждого блока хранится в отдельной папке проекта. Каждая технология (CSS, JavaScript, тесты, шаблоны, документация, изображения) находится в отдельном файле.

Например, если внешний вид блока input задан с помощью CSS, код сохраняется в файле input.css .

 project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript

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

 project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript input_theme_sun.css # The "input_theme_sun" modifier implementation input__clear.css # The "input__clear" element implementation with CSS input__clear.js # The "input__clear" element implementation with JavaScript

Чтобы улучшить навигацию по проекту, комбинируйте модификаторы блоков с несколькими значениями в каталогах.

Файловая структура любого БЭМ-проекта состоит из уровней переопределения (подробнее о них можно узнать здесь). Уровни переопределения позволяют:

  • Разделите проект на платформы;
  • Легко обновлять библиотеки блоков, включенные в проект;
  • Используйте общие блоки для разработки нескольких проектов;
  • Меняйте темы оформления, не затрагивая логику проекта;
  • Проводите эксперименты в реальном проекте.

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

Неочевидные преимущества методологии

Удобство параллельной разработки

В БЭМ любая раскладка разбита на блоки. Поскольку блоки независимы, они могут разрабатываться параллельно несколькими разработчиками.

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

Примером может служить библиотека блоков bem-components, которая содержит универсальные блоки, такие как ссылка, кнопка и поле ввода. Из универсальных компонентов проще создавать более сложные блоки. Например, селектор или флажок.

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

Тестирование макета

Проблемно протестировать работоспособность всей страницы, особенно в динамическом проекте, подключенном к базе данных.

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

Настраиваемая сборка проекта

Для удобства разработки все блоки и технологии в БЭМ-проекте размещены в отдельных папках и файлах. Чтобы объединить исходные файлы в один файл (например, поместить все CSS-файлы в project.css , все JS-файлы в project.js и т. д.), мы используем процесс сборки.

Сборка выполняет следующие задачи:

  • Объединяет исходные файлы, разбросанные по файловой системе проекта;
  • Включает в проект только необходимые блоки, элементы и модификаторы (БЭМ-сущности);
  • Следует порядку включения сущностей;
  • Обрабатывает код исходного файла во время сборки (например, компилирует МЕНЬШЕ код в код CSS).

Чтобы включить в сборку только необходимые БЭМ-сущности, необходимо создать список блоков, элементов и модификаторов, используемых на страницах. Этот список называется декларацией .

Поскольку БЭМ-блоки разрабатываются независимо и размещаются в отдельных файлах файловой системы, они ничего не «знают» друг о друге. Чтобы строить блоки на основе других блоков, укажите зависимости. За это отвечает БЭМ-технология: файлы deps.js Файлы зависимостей сообщают механизму сборки, какие дополнительные блоки необходимо включить в проект.

Практический пример: БЭМ подходит не только для CSS

В предыдущих разделах все примеры кода относятся к CSS. Но БЭМ позволяет изменять поведение блока и его представление в HTML таким же декларативным способом, как и в CSS.

Как использовать шаблоны в БЭМ

В HTML разметка блока повторяется каждый раз, когда блок появляется на странице. Если вы создаете HTML-разметку вручную, а затем вам нужно исправить ошибку или внести изменения, вам потребуется изменить разметку для каждого экземпляра блока. Для генерации HTML-кода и автоматического применения исправлений БЭМ использует шаблоны; блоки отвечают за то, как они представлены в HTML.

Шаблоны позволяют:

  • Сокращение времени, затрачиваемого на отладку проекта, поскольку изменения шаблона автоматически применяются ко всем блокам проекта;
  • Изменить макет блока;
  • Переместить блоки с текущим макетом в другой проект.

БЭМ использует механизм шаблонов bem-xjst, который имеет два механизма:

  • BEMHTML
    Преобразует BEMJSON-описание страницы в HTML. Шаблоны описаны в файлах .bemhtml.js.
  • БЕМТРИ
    Преобразует данные в BEMJSON. Шаблоны описаны в формате BEMJSON в файлах .bemtree.js.

Если для блоков не написаны шаблоны, механизм шаблонов по умолчанию устанавливает <div> для блоков.

Сравните объявление блоков и вывод HTML:

Декларация:

 { block: 'menu', content: [ { elem: 'item', content: { block: 'link'} }, { elem: 'item', elemMods: { current: true }, // Set the modifier for the menu item content: { block: 'link' } } ] }

HTML:

 <div class="menu"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div>

Чтобы изменить макет блока menu , вам нужно написать шаблоны для блока:

  1. Изменим тег блока menu :
     block('menu')( tag()('menu') // Set the "menu" tag for the menu block )

    Измененный HTML:
     <menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </menu>

    Подобно CSS, шаблон применяется ко всем блокам «меню» на странице.
  2. Добавьте дополнительный элемент ( menu__inner ), который работает как внутренняя оболочка и отвечает за расположение элементов в блоке menu . Изначально элемент menu__inner не был включен в объявление, поэтому мы должны добавить его при построении шаблонов.

    БЭМ-шаблоны написаны на JavaScript, поэтому вы также можете использовать JavaScript для добавления в шаблон нового элемента:
     block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content }; }) )
     <menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__inner"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div> </menu>
  3. Замените теги для всех inner элементов и item элемента:
     block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) )
     <menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <div class="link"></div> </li> <li class="menu__item menu__item_current"> <div class="link"></div> </li> </ul> </menu>
  4. Установите тег <a> для всех ссылок на странице:
     block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) ); block('link')( tag()('a') );
     <menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <a class="link"></a> </li> <li class="menu__item menu__item_current"> <a class="link"></a> </li> </ul> </menu>
  5. Измените существующий шаблон. Правила в шаблонах применяются так же, как и в CSS: правило более низкого уровня имеет приоритет над правилом более высокого уровня. Добавьте в шаблон новые правила и измените тег ссылки с <a> на <span> :
     block('link')( tag()('a') ); block('link')( tag()('span') );
     <menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <span class="link"></span> </li> <li class="menu__item menu__item_current"> <span class="link"></span> </li> </ul> </menu>

БЭМ — это настраиваемая система

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

Теперь вы можете настроить систему и сделать своего супергероя из БЭМ!

БЭМ как логотип Капитана Америки
БЭМ Капитан Америка

Как получить больше от БЭМ

Чтобы начать изучение принципов БЭМ, посетите наш веб-сайт. Если у вас есть какие-либо вопросы, которые вы хотели бы задать команде, присоединяйтесь к нашему каналу Telegram или откройте обсуждение на нашем форуме BEM.