Введение
БЭМ (Блок, Элемент, Модификатор) - компонентный подход к веб-разработке. В его основе лежит принцип разделения интерфейса на независимые блоки. Он позволяет легко и быстро разрабатывать интерфейсы любой сложности и повторно использовать существующий код, избегая «Copy-Paste».
Блок
Функционально независимый компонент страницы, который может быть повторно использован. В HTML блоки представлены атрибутом class.
Особенности:
Пример:
<!-- Верно. Семантически осмысленный блок `error` --> <div class="error"></div> <!-- Неверно. Описывается внешний вид --> <div class="red-text"></div>
Таким образом обеспечивается независимость, при которой возможно повторное использование или перенос блоков с места на место.
- Принципы работы с блоками
<!-- Блок `header` --> <header class="header"> <!-- Вложенный блок `logo` --> <div class="logo"></div> <!-- Вложенный блок `search-form` --> <form class="search-form"></form> </header>
Элемент
Составная часть блока, которая не может использоваться в отрыве от него.
Особенности:
Пример:
<!-- Блок `search-form` --> <form class="search-form"> <!-- Элемент `input` блока `search-form` --> <input class="search-form__input"> <!-- Элемент `button` блока `search-form` --> <button class="search-form__button">Найти</button> </form>
- Принципы работы с элементами
Вложенность
Пример:
<!-- Верно. Структура полного имени элементов соответствует схеме: `имя-блока__имя-элемента` --> <form class="search-form"> <div class="search-form__content"> <input class="search-form__input"> <button class="search-form__button">Найти</button> </div> </form> <!-- Неверно. Структура полного имени элементов не соответствует схеме: `имя-блока__имя-элемента` --> <form class="search-form"> <div class="search-form__content"> <!-- Рекомендуется: `search-form__input` или `search-form__content-input` --> <input class="search-form__content__input"> <!-- Рекомендуется: `search-form__button` или `search-form__content-button` --> <button class="search-form__content__button">Найти</button> </div> </form>
Имя блока задает пространство имен, которое гарантирует зависимость элементов от блока (block__elem).
Принадлежность
Элемент - всегда часть блока и не должен использоваться отдельно от него.
Пример:
<!-- Верно. Элементы лежат внутри блока `search-form` --> <!-- Блок `search-form` --> <form class="search-form"> <!-- Элемент `input` блока `search-form` --> <input class="search-form__input"> <!-- Элемент `button` блока `search-form` --> <button class="search-form__button">Найти</button> </form> <!-- Неверно. Элементы лежат вне контекста блока `search-form` --> <!-- Блок `search-form` --> <form class="search-form"> </form> <!-- Элемент `input` блока `search-form` --> <input class="search-form__input"> <!-- Элемент `button` блока `search-form` --> <button class="search-form__button">Найти</button>
Необязательность
Элемент - необязательный компонент блока. Не у всех блоков должны быть элементы.
Пример:
<!-- Блок `search-form` --> <div class="search-form"> <!-- Блок `input` --> <input class="input"> <!-- Блок `button` --> <button class="button">Найти</button> </div>
Когда создавать блок, когда - элемент?
- Создавайте блок
Если фрагмент кода может использоваться повторно и не зависит от реализации других компонентов страницы.
- Создавайте элемент
Если фрагмент кода не может использоваться самостоятельно, без родительской сущности (блока).
Исключение составляют элементы, реализация которых для упрощения разработки требует разделения на более мелкие части - подэлементы. В БЭМ-методологии нельзя создавать элементы элементов. В подобном случае вместо элемента необходимо создавать служебный блок.
Модификатор
Cущность, определяющая внешний вид, состояние или поведение блока либо элемента.
Особенности:
- Типы модификаторов
Булевый
Пример:
<!-- Блок `search-form` имеет булевый модификатор `focused` --> <form class="search-form search-form_focused"> <input class="search-form__input"> <!-- Элемент `button` имеет булевый модификатор `disabled` --> <button class="search-form__button search-form__button_disabled">Найти</button> </form>
Ключ-значение
Пример:
<!-- Блок `search-form` имеет модификатор `theme` со значением `islands` --> <form class="search-form search-form_theme_islands"> <input class="search-form__input"> <!-- Элемент `button` имеет модификатор `size` со значением `m` --> <button class="search-form__button search-form__button_size_m">Найти</button> </form> <!-- Невозможно одновременно использовать два одинаковых модификатора с разными значениями --> <form class="search-form search-form_theme_islands search-form_theme_lite"> <input class="search-form__input"> <button class="search-form__button search-form__button_size_s search-form__button_size_m"> Найти </button> </form>
- Принципы работы с модификаторами
С точки зрения БЭМ-методологии модификатор не может использоваться в отрыве от модифицируемого блока или элемента. Модификатор должен изменять вид, поведение или состояние сущности, а не заменять ее.
Пример:
<!-- Верно. Блок `search-form` имеет модификатор `theme` со значением `islands`--> <form class="search-form search-form_theme_islands"> <input class="search-form__input"> <button class="search-form__button">Найти</button> </form> <!-- Неверно. Отсутствует модифицируемый класс `search-form` --> <form class="search-form_theme_islands"> <input class="search-form__input"> <button class="search-form__button">Найти</button> </form>
БЭМ-сущность
БЭМ-сущностями называются блоки, элементы и модификаторы.
Это понятие может применяться как частное, если рассматривается отдельная БЭМ-сущность, и как собирательное для блоков, элементов и модификаторов.
Микс
Способ использования разных БЭМ-сущностей на одном DOM-узле.
Миксы позволяют:
Рассмотрим пример микса блока и элемента другого блока.
Допустим, в проекте ссылки реализованы блоком link. Необходимо сделать ссылками пункты меню. Существует несколько способов:
БЭМ-дерево
Представление структуры веб-страницы в терминах блоков, элементов и модификаторов. Это абстракция над DOM-деревом, которая описывает имена БЭМ-сущностей, их состояния, порядок, вложенность и вспомогательные данные. В реальных проектах БЭМ-дерево можно выразить любым форматом, который поддерживает древовидную структуру.
Рассмотрим пример DOM-дерева:
<header class="header"> <img class="logo"> <form class="search-form"> <input class="input"> <button class="button"></button> </form> <ul class="lang-switcher"> <li class="lang-switcher__item"> <a class="lang-switcher__link" href="url">en</a> </li> <li class="lang-switcher__item"> <a class="lang-switcher__link" href="url">ru</a> </li> </ul> </header>
Ему соответствует такое БЭМ-дерево:
header logo search-form input button lang-switcher lang-switcher__item lang-switcher__link lang-switcher__item lang-switcher__link
Соглашение по именованию
Имя БЭМ-сущности уникально. Во всех технологиях (CSS, JavaScript, HTML) одна и та же БЭМ-сущность всегда называется одинаково. Основная идея соглашения по именованию - вложить смысл в имена и сделать их максимально информативными для разработчика.
Можно сравнить одно и тоже имя CSS-селектора, написанное разными способами:
Чтобы понять смысл первого имени, нужно вчитаться в каждое слово. В последних двух примерах имя явно разделяется на логические части. Но ни одно из имен пока не помогает точно определить, что menu - это блок, item - элемент, а visible - модификатор. Чтобы имена сущностей были однозначными и понятными, в БЭМ были разработаны правила формирования имен БЭМ-сущностей.
- Правила формирования имен
block-name__elem-name_mod-name_mod-val
Важно! В методологии БЭМ не существует элементов элементов. Правила именования запрещают создавать элементы элементов, но в DOM-дереве элементы можно вкладывать друг в друга.
Примеры:
- Имя блока
menu
HTML: <div class="menu">...</div> CSS: .menu { color: red; }
- Имя элемента
menu__item
HTML: <div class="menu"> ... <span class="menu__item"></span> </div> CSS: .menu__item { color: red; }
- Имя модификатора блока
menu_hidden
menu_theme_islands
HTML: <div class="menu menu_hidden">...</div> <div class="menu menu_theme_islands">...</div> CSS: .menu_hidden { display: none; } .menu_theme_islands { color: green; }
- Имя модификатора элемента
menu__item_visible
menu__item_type_radio
HTML: <div class="menu"> ... <span class="menu__item menu__item_visible menu__item_type_radio">...</span> </div> CSS: .menu__item_visible {} .menu__item_type_radio { color: blue; }
Альтернативные схемы именования
- Стиль Two Dashes
block-name__elem-name--mod-name--mod-val
- Стиль CamelCase
blockName__elemName_modName_modVal
- Стиль React
BlockName-ElemName_modName_modVal