Форум

Методология

Toolbox

Платформа

Сообщество

Часто задаваемые вопросы

Почему БЭМ?

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

JavaScript

CSS

Не нашли ответ?Задайте вопрос команде на форуме

В чем отличие БЭМ от OOCSS, AMCSS, SMACSS, SUITCSS?

  1. БЭМ работает не только с CSS, но и с JavaScript.
  2. БЭМ больше схож с Web Components, чем с перечисленными решениями для CSS. (В чем разница между БЭМ и Web Components?)
  3. БЭМ предоставляет комплексное решение по созданию архитектуры проекта и помогает организовать процессы разработки. Подробнее читайте в разделе Применение методологии для решения задач веб-разработки.

Подробнее о методологии БЭМ.

Можно использовать БЭМ только на уровне CSS. Для этого достаточно просто следовать рекомендациям методологии.

В чем разница между БЭМ и Web Components?

Поддержка браузеров

Инкапсуляция

Работа шаблонов

Вместо импорта HTML — сборка

Вместо Custom Elements — абстракция над DOM-деревом

В чем разница между БЭМ и Bootstrap?

В терминах БЭМ Bootstrap — это набор сверстанных блоков. БЭМ — не библиотека элементов интерфейса, а методология, позволяющая:

Библиотека блоков, сделанных на БЭМ — bem-components. Существуют также и другие БЭМ-библиотеки.

В каком случае создавать блок, в каком — элемент?

  1. Если фрагмент кода может использоваться повторно и не зависит от реализации других компонентов страницы, необходимо создавать блок.
  2. Если фрагмент кода не может использоваться самостоятельно, без родительской сущности (блока), в большинстве случаев создается элемент.

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

Почему в БЭМ не рекомендуется создавать элементы элементов (block__elem1__elem2)?

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

В методологии БЭМ вложенную структуру поддерживают только блоки (block__elem). Имя блока задает пространство имен, которое гарантирует зависимость элементов от блока.

Блок может иметь вложенную структуру элементов в DOM-дереве:

<div class="block">
    <div class="block__elem1">
        <div class="block__elem2">
            <div class="block__elem3"></div>
        </div>
    </div>
</div>

Однако эта же структура блока в методологии БЭМ всегда будет представлена плоским списком элементов:

.block {}
.block__elem1 {}
.block__elem2 {}
.block__elem3 {}

Это позволяет изменять DOM-структуру блока без внесения правок в коде каждого отдельного элемента:

<div class="block">
    <div class="block__elem1">
        <div class="block__elem2"></div>
    </div>
    <div class="block__elem3"></div>
</div>

Структура блока меняется, а правила для элементов и их названия остаются прежними.

Зачем писать имя блока в именах модификаторов и элементов?

Имя блока в именах БЭМ-сущностей обеспечивает:


Важно! Методология БЭМ допускает выбор удобной стратегии именования, но требует соблюдения консистентности в названиях. Так, например, все варианты верны: context, ctx или c, attributes, attrs или as. Необходимо выбрать один из них и использовать во всем проекте.


Пространство имен

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

Миксы

Микс — это совмещение разных БЭМ-сущностей на одном DOM-узле. При миксе модификатора имя блока указывает, к какому блоку применится модификатор. Если имя блока не указать, модификатор применится ко всем миксуемым БЭМ-сущностям.

Например, рассмотрим микс пункта меню (menu__item) и кнопки (button):

<div class="menu__item button"></div>

Добавим модификатор active в сокращенной форме записи (без имени блока):

<div class="menu__item button active"></div>

В таком виде HTML-разметка не дает понять, к чему относится модификатор: к пункту меню (menu__item.active) или к кнопке (button.active). Имя блока (button_active) явно указывает на БЭМ-сущность, к которой будет применен модификатор.

Также запись <div class="block mod"> не дает понять, какие БЭМ-сущности используются в работе. Например, из записи <div class="checkbox button"> нельзя однозначно определить, это микс модификатора и блока или микс двух блоков.

Полное имя модификатора <div class="block block_mod"> показывает, о каких сущностях идет речь: <div class="checkbox checkbox_button">.

Поиск в коде

Явные и уникальные имена облегчают поиск необходимой сущности в коде и файловой системе.

Сравним результаты глобального поиска при отладке проекта. Найдем модификатор active. В сокращенном виде (active) в результаты поиска попадут все возможные комбинации и HTML-фрагменты, где встречается active. В записи, рекомендуемой методологией, само название уже будет содержать уточняющий параметр в виде имени блока (button_active). Так как имя модификатора уникально, в результаты поиска попадут только нужные фрагменты кода.

Как сделать глобальные модификаторы для блоков?

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

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

БЭМ позволяет совмещать реализацию разных блоков с помощью миксов:

<div class="block1 block2"></div>

Зачем создавать отдельные директории и файлы для каждого блока и технологии?

Файловая система БЭМ-проекта разделяется на вложенные директории и файлы для удобства разработки и поддержки проекта.

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

flex-схема

blocks/
  input/
      input_layout_horiz.css
      input_layout_vertical.css
      input__elem.css
      input.css
      input.js
  button/
blocks/
  input/
      input.css
      input.js
  button/
blocks/
  input.css
  input.js
  button.css
  button.js

flat-схема

blocks/
  input_type_search.js
  input_type_search.bemhtml
  input__box.bemhtml
  input.css
  input.js
  input.bemhtml
  button.css
  button.js
  button.bemhtml
  button.png

Зачем использовать i-bem.js, если можно писать на jQuery?

i-bem.js это специализированный фреймворк для разработки проектов на JavaScript в терминах блоков, элементов и модификаторв.

i-bem.js не предназначен для замены фреймворка общего назначения, такого как jQuery.

i-bem.js позволяет:

Почему нежелательно использовать вложенные селекторы?

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

Методология БЭМ допускает использование таких селекторов, но рекомендует по-максимуму его сократить.

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

.nav_hovered .nav__link
{
    text-decoration: underline;
}
.nav_theme_islands .nav__item
{
    line-height: 1.5;
}

Почему в БЭМ не рекомендуется использовать комбинированные селекторы для создания CSS-правил к модификатору?

Комбинированные селекторы усложняют переопределение блока, так как имеют более высокую специфичность в CSS, чем одиночные. Специфичность комбинированного селектора для модификатора блока (.block1.mod) и для переопределенного блока (.block2 .block1) одинакова. Переопределение блока будет зависеть только от порядка объявления правил в декларации.

Рассмотрим пример:

<div class="header">
  <button class="button active">
</div>

Правила модификатора active для кнопки записываются как комбинированный селектор .button.active. При переопределении кнопки с помощью родительского блока header, создается селектор .header .button. Специфичность обоих селекторов одинакова, значит применение CSS-правил определяется порядком их объявления в декларации.

Использование имени блока в названии модификатора обеспечивает более высокий приоритет CSS-правилам при переопределении блока. Селектор .header .button всегда будет иметь приоритет выше, чем .button_active.

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

Можно ли объединять тег и класс в селекторе? Например, button.button.

Совмещение тега и класса в селекторе повышает специфичность CSS-правил. При добавлении модификатора правила блока не смогут быть переопределены, так как специфичность селектора блока выше.

Рассмотрим пример:

 <button class="button">

Записываем для него CSS-правила в селекторе button.button.

Добавим модификатор:

 <button class="button button_active">

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

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

Почему в БЭМ не используют пользовательские теги (custom tags) для блоков?

Блоки могут выражаться в HTML с помощью пользовательских тегов, к которым создаются CSS-правила. В таком случае классы можно будет использовать только для модификаторов: <button class="mod"/>.

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

Почему нельзя делать общий сброс стилей (reset)?

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

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

Если сбросить стили все-таки необходимо, в БЭМ это делается в каждом блоке.

Рассмотрим пример. Если в проекте блоки меню и список выражены в HTML с помощью тега <ul>, значит каждый блок должен предоставлять сброс CSS для <ul>. Повторов в результирующем коде можно избежать с помощью CSS-оптимизатора.

Если в проекте не используется CSS-оптимизатор, который объединяет селекторы с одинаковым набором правил, можно применить CSS-препроцессор. Тогда для каждого нового блока можно делать сброс правил, миксуя чистый код. Например, в SASS это будет выглядеть так:

.menu {
    @include reset-list;
}
.menu__item {
    @include reset-list-item;
}
...
.list {
    @include reset-list;
}
.list__item {
    @include reset-list-item;
}

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

Почему нельзя писать block_mod вместо block block_mod, если имя модификатора уже содержит всю информацию о блоке?

Совмещение нескольких модификаторов на одном и том же блоке (например, <div class="block_theme_christmas block_size_big">) приведет к дублированию кода, реализующего базовую функциональность (логику и стили) блока.

Почему нельзя указывать название CSS-свойства в имени модификатора: .block__element_border-color_grey?

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

Если вы заметили ошибку или хотите чем-то дополнить статью, вы всегда можете или написать нам об этом на Гитхабе, или поправить статью с помощью prose.io.