Форум

Методология

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

Платформа

Сообщество

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

Почему БЭМ?

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

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

CSS

JavaScript

У меня другой вопрос. Если вы не нашли ответ на свой вопрос, то вы можете задать его нам на форуме.

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

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

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

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

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

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

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

  • В Web Components реализована через Shadow DOM.
  • В БЭМ — с помощью элементов блока.

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

  • В Web Components шаблоны всегда выполняются в браузере. Это может потребовать дополнительных решений проблем с индексацией.
  • В БЭМ генерация шаблона возможна на этапе разработки. Это позволяет отдавать готовый HTML. Шаблоны могут выполняться как в браузере, так и на сервере.
  • Web Components использует императивный принцип — интерполяцию строк.
  • БЭМ использует декларативный подход, который позволяет гибко управлять шаблонизацией и избегать повторений.

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

  • Web Components использует импорт HTML (HTML Imports), который работает непосредственно в браузере. Для объединения HTML-файлов используется инструмент Vulcanize.
  • В БЭМ-платформе используются следующие сборщики:

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

  • В Web Components используются Custom Elements. Такой подход позволяет разместить на одном DOM-узле только один компонент.
  • В БЭМ существует понятие БЭМ-дерева. Для размещения на одном DOM-узле нескольких БЭМ-сущностей используются миксы.

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

В терминах БЭМ Bootstrap — это свободный набор сверстанных блоков для создания сайтов и веб-приложений.

БЭМ — это методология, позволяющая:

  • создавать архитектуру проекта;
  • разрабатывать веб-приложения независимыми блоками;
  • упрощать поддержку проектов.

Также существует ряд библиотек с открытым исходным кодом:

  • bem-components — библиотека блоков, содержащая контролы форм и другие базовые компоненты веб-интерфейса;
  • bem-core — библиотека блоков, предоставляющая специализированный JavaScript-фреймворк для веб-разработки.
  • bem-history — БЭМ-обертка над History API.

Когда создавать блок, когда — элемент?

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

Как правильно изменять внешний вид каждого экземпляра блока на странице?

Изменять внешний вид одного и того же блока можно с помощью:

  • модификаторов — применяется, если существует вероятность переиспользовать блок в данном оформлении;
  • миксов — применяется, если блок имеет специфичное оформление только для данного окружения и в данном виде точно не будет переиспользован на проекте.

Подробнее про применение миксов и модификаторов читайте в разделе Когда создавать модификатор, когда — микс?.

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

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

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

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

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

Миксы

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

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

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

Добавим модификатор active не указав имени блока:

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

В таком виде HTML-разметка не дает понять:

  • к чему относится модификатор (к пункту меню menu__item.active или к кнопке button.active);
  • о каких БЭМ-сущностях идет речь (это микс модификатора и блока или микс двух блоков).

Включая имя блока в имя модификатора, HTML-разметка становится информативней и понятней:

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

Поиск в коде

Уникальные имена облегчают идентификацию сущностей в коде и на файловой структуре.

Гораздо проще найти все совпадения с button_active, чем просто с active, так как в результаты поиска попадут все возможные комбинации: select_active, checkbox_active, menu__item_active и т.п.

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

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

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

Могут ли элементы блока наследовать его CSS-свойства?

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

Таким образом, если вы хотите одинаково стилизовать все элементы блока, целесообразно задать CSS-правила непосредственно блоку. Если же элементы блока должны иметь разнообразное оформление, то CSS-правила определяются непосредственно для элементов. Возникшие при этом повторы в результирующем коде можно избежать с помощью CSS-оптимизатора, который объединит селекторы с одинаковым набором CSS-правил.

Можно ли создавать блоки-обертки?

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

Подробнее читайте в разделе HTML для CSS.

Можно ли создавать элементы элементов (block__elem1__elem2)?

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

Подробнее читайте в разделе Быстрый старт.

Когда создавать модификатор, когда — микс?

Создавайте модификатор

Если нужная вам реализация может использоваться повторно и не зависит от реализации других компонентов страницы. Например, блок select имеет модификаторы: hovered, focused, opened.

Модификаторы блока select

Создавайте микс

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

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

  • реализуется определенная бизнес-логика проекта;
  • задается внешняя геометрия для данного окружения.

Когда создавать булевый модификатор, когда — модификатор «ключ-значение»?

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

  • Для булевых модификаторов — block-name_mod-name.
  • Для модификаторов вида «ключ-значение» — block-name_mod-name_mod-val.

Создавайте булевый модификатор

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

Пример

<div class="button button_disabled">...</div>
<div class="checkbox checkbox_checked">...</div>

Создавайте модификатор вида «ключ-значение»

Если состояний у блока может быть несколько. Например, для описания размеров блока можно использовать модификатор size с допустимыми значениями s, m и l.

Пример

<div class="button button_size_s">...</div>
<div class="button button_size_m">...</div>

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

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

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

HTML-реализация:

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

Имя модификатора button_background_yellow неудачное, потому что:

  • При изменении фона с желтого (yellow), например, на красный (red) придется менять не только CSS-код, но и название селектора, шаблоны и, вполне вероятно, JavaScript-код.
  • При добавлении других CSS-свойств, например, border, line-height, имя модификатора перестанет соответствовать его содержанию.

Удачное имя:

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

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

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

  • именем блока;
  • именем элемента.

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

Подробнее читайте в разделе Стилизация групп блоков.

Почему нельзя писать имя модификатора блока в имени элемента (block_mod__elem)?

Элемент — составная часть блока, а не модификатора блока. Таким образом, только имя блока может задавать пространство имен для элементов.

Это важно, потому что:

  • Блок может иметь много модификаторов.

    <div class="block block_mod1 block_mod2 block_mod3">
        <div class="block__elem">...</div>
    </div>
    
  • Модификатор определяет состояние блока/элемента, которое может быть изменено во время выполнения скрипта JavaScript.

Как адаптировать сайт к различным устройствам?

Существует несколько способов изменять разметку страницы на основе ширины окна браузера:

В обоих случаях необходимо определить контрольные точки (breakpoints), условия, при которых раскладка сайта меняется с одной на другую.

Media Queries

Файловая структура:

common.blocks/
    button/
        button.css    # CSS-реализация кнопки

CSS-реализация:

@media (max-width: 767px) {
    .button {
          left: 0;
    }
}

@media (max-width: 479px) {
    .button {
        right: 0;
    }
}

Примечание Имена блоков должны быть достаточно общими, для того чтобы его можно было использовать более чем с одной целью. Не стоит называть блок sidebar-left, если при изменении ширины экрана, его позиция изменится на right.

Переключение модификатора

Файловая структура:

common.blocks/
    button/
        _position/
            button_position_left.css   
            button_position_left.css    
        button.js                         # JS-реализация кнопки

button_position_left.css:

.button_position_left {
    left: 0;
}

button_position_right.css:

.button_position_right {
    right: 0;
}

Изменение CSS-классов на DOM-узле происходит при помощи JavaScript.

Подробнее читайте в разделе Переключение модификаторов.

Можно ли совмещать теги и классы в селекторе?

Совмещение тега и класса в селекторе повышает специфичность CSS-правил. Методология БЭМ не рекомендует совмещать теги и классы в селекторе.

Подробнее читайте в разделе Совмещение тега и класса в селекторе.

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

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

Подробнее читайте в разделе Вложенные селекторы.

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

Комбинированные селекторы имеют более высокую специфичность CSS-правил, чем одиночные. Успешность переопределения таких селекторов сильно привязана к порядку их объявления. Методология БЭМ не рекомендует использовать комбинированные селекторы.

Подробнее читайте в разделе Комбинированные селекторы.

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

В HTML блоки могут выражаться с помощью пользовательских HTML-элементов (Custom Elements) с целью:

  • улучшить структуру веб-страницы и добавить смысловое значение заключенному в них содержимому;
  • как следствие, использовать селекторы по пользовательским тегам вместо селекторов по классам;
  • связать с HTML-элементом дополнительные данные, с которыми потом будет работать JavaScript.

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

Пример

HTML-реализация:

<icon-twitter class="icon_social_twitter">...</icon-twitter>

CSS-реализация:

icon-twitter {}
.icon_social_twitter {}

В таком подходе существует ряд ограничений:

  • невозможно использовать миксы;
  • не любой блок можно выразить пользовательским HTML-элементом. Например, для всех ссылок необходим тег <a>, а для полей — <input>.

Можно ли делать общий сброс стилей (reset)?

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

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

Пример

CSS-реализация:

ul, ol {
    list-style: none;
}

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

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

Допустим, в проекте блоки .menu и .list выражены HTML-тегом <ul>, для которого необходимо сделать сброс. Следовательно каждый блок должен сбросить стили для <ul>. Возникшие при этом повторы в результирующем коде можно избежать с помощью CSS-оптимизатора, который объединит селекторы с одинаковым набором CSS-правил.

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

Например, в SASS это будет выглядеть так:

/* Сброс стилей для HTML-тега `<ul>` */
.menu {
    @include reset-list;
}
...
/* Сброс стилей для HTML-тега `<ul>` */
.list {
    @include reset-list;
}

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

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

Если оставить только класс модификатора без указания класса самого блока/элемента, то все базовые CSS-свойства блока необходимо будет определить в селекторе css .block_mod {}.

Модификаторы могут изменяться как в процессе работы блока (например, как реакция на DOM-события блока), так и по запросу из других блоков. Таким образом, копировать базовые CSS-свойства блока, придется во все его модификаторы.

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

Можно ли создавать вспомогательные классы?

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

Примером вспомогательного блока в bem-core может служить блок clearfix, а в bem-components — z-index-group.

Подробнее о применении миксов читайте в разделе Стилизация групп блоков.

Почему внешнюю геометрию и позиционирование задают через родительский блок?

Идея БЭМ — создавать расширяемые и повторно используемые компоненты интерфейса. Если вы создаете блок, который возможно будет переиспользован, то целесообразно сделать так, чтобы сам блок «ничего не знал» про те CSS-свойства, которые помешают это сделать.

К таким CSS-свойствам можно отнести:

  • margin;
  • position.

Подробнее читайте в разделе Внешняя геометрия и позиционирование

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

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

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

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

  • разрабатывать веб-интерфейс в терминах блоков, элементов, модификаторов;
  • интегрировать JavaScript-код с шаблонами и CSS-правилами в стиле БЭМ;
  • описывать логику работы блока как набор состояний.
Если вы заметили ошибку или хотите чем-то дополнить статью, вы всегда можете или написать нам об этом на Гитхабе, или поправить статью с помощью prose.io.