Приветствую Вас дорогой коллега! Сегодня я хочу рассказать про такую технологию в веб-разработке, как БЭМ. А если точнее то, как называть классы объектам документа при верстке. Помню, когда я начинал и не знал про всякие методики типа БЭМ’а мне сложно было придумывать классы, я постоянно путался, у меня постоянно было пересечение классов, что в итоге сильно тормозило работу.
БЭМ (Блок, Элемент, Модификатор) — это не только простое именование классов, это компонентный подход к работе. Компонентный подход — это когда мы делим разрабатываемый интерфейс на отдельные блоки. При надобности данный блок можем использовать в другой части сайта или приложения без дублирования стилей. Сейчас конечно же мало, что понятно, но мы будем разбирать примеры.
Основу БЭМ методологии составляют 3 составляющие:
- Блок;
- Элемент;
- Модификатор.
Их еще называют БЭМ сущности. Ниже мы разберем каждую сущность по отдельности.
Сразу хочу отметить, что по БЭМ’у написана отличная документация на русском языке, усваивается очень легко и просто. Я лично данную документацию перечитывал несколько раз. В первое время я испытывал сложности, а именно когда создавать блок, когда элемент, а модификаторы и вовсе не использовал или использовал не по методике. Теперь наконец-то встало все на свои места.
В данной своей инструкции я пройдусь кратко по тем пунктам, которые сам использую в БЭМ и которых мне достаточно, чтобы писать красивый и понятный код. Удобство кода тоже играет большую роль в веб-разработке — и вам понятно, и другим разработчикам, которые могут работать над проектом после вас.
Блок
Блоком в БЭМ называют функционально независимый компонент, который может быть повторно использован на любой странице сайта и в любой части документа. Блок именуется только атрибутом class
. Название блока (а именно присваемовый класс) должно характеризовать смысл или предназначение блока (что это — «шапка сайта»: header
; «меню»: menu
; «виджет»: widget
и т. д.), а не его состояние (какой, состояние — «красный»: red
; «активный»: active
и т. п.).
<!-- Верно. Шапка сайта - это блок, предназначение его понятно какое -->
<header class="header"></header>
Вот еще пример блока:
<!-- Верно. Блок формы -->
<form class="form"></form>
А вот это уже будет неправильно:
<!–- Неверно. Здесь описывается класс с большим текстом -–>
<div class="big-text"></div>
Не стоит задавать блокам внешние отступы или стили, которые могут повлиять на его размер, а также позиционирование. И это по той причине, что мы можем использовать данный блок повторно в другом месте. Мы добиваемся некой независимости и в таком случае не придется ничего переопределять.
Вложенность блоков
Блоки могут быть вложены один в другой. Например в блоке шапки сайта может быть вложен блок логотипа.
<header class="header">
<div class="logo">...</div>
</header>
Микс блоков
Блоки можно также и миксовать (перемешивать), т. е. совмещение нескольких сущностей в одном блоке. В основном микс используют для переопределения блока в разных частях сайта. Давайте рассмотрим пример.
<header class="header">
<div class="logo header__logo">...</div>
</div>
В данном примере мы блоку logo
задали дополнительный класс header__logo
, тем самым переопределяя блок logo
в шапке сайта header
(к примеру, в шапке сайта логотип можно уменьшить до определенных размеров, оставляя все остальное как есть).
Элемент
Элемент — это составляющая блока, которая не может быть использована в отрыве от него. Именование элемента выглядит следующим образом: имя-блока__имя-элемента
. То есть название элемента отделяется от имени блока двойным нижним подчеркиванием (__). Также, как и для блока название элемента нужно задавать правильно: "что это?" — "пункт": item, "текст": text
, т. е. характеризует смысл, а не состояние объекта: "красный": red, "большой": big
. Думаю, здесь все понятно. Теперь давайте рассмотрим небольшой пример.
<!--
Верно!
Блок: logo
-->
<div class="logo">
<!-- Элемент лого: name -->
<div class="logo__name">Название</div>
<!-- Элемент лого: slogan -->
<div class="logo__slogan">Слоган</div>
</div>
Как уже было отмечено, элементы не могут быть сами по себе вне блока. То есть в примере ниже будет неправильно.
<!-- Неверно! -->
<div class="logo">...</div>
<div class="logo__name">Имя логотипа</div>
<div class="logo__slogan">Слоган логотипа</div>
Элементы могут быть вложены один в другой. Структура DOM-дерева будет примерно следующей:
<div class="block">
<div class="block__elem1">
<div class="block__elem2">
<div class="block__elem3"></div>
</div>
</div>
</div>
Вообще такой подход именования классов задает пространство имен элементам, но в тоже время они зависят от блока. Правила в файле стилей будет представлен плоским списком и будет удобочитаем.
Css
.block {}
.block__elem1 {}
.block__elem2 {}
.block__elem3 {}
Sass
.block
&__elem1
&__elem2
&__elem3
Мы можем менять порядок элементов в блоке, но это не отразится в правилах css и не испортит структуру.
<div class="block">
<div class="block__elem1">
<div class="block__elem2">...</div>
</div>
<div class="block__elem3">...</div>
</div>
Хочу отметить, что элемент не обязателен для блока. То есть блок может быть и без элементов, а элемент, как вы уже знаете, без блока быть не может.
Когда создавать блок, а когда элемент?
Блок
Хороший вопрос, сам им когда-то задавался. Но практика мне подсказала, что создавать блок нужно, если он может быть использован повторно в другом месте. Например, у нас на сайте есть формы. Сам блок формы дизайнер нарисовал в едином стиле, но отличаются только незначительно в разных частях страницы. Форма может быть в модальном окне, может быть встроена прямо в тело статьи, может быть блоком обратной связи и т.д. Таким образом мы создаем единый блок, который может использоваться несколько раз.
<form class="form" action="#" method="post">
<input type="text" name="name" class="form__input" />
<input type="text" name="email" class="form__input" />
<input type="text" name="phone" class="form__input" />
<input type="submit" class="form__btn" value="Отправить" />
</form>
Элемент
Создавайте элемент тогда, когда элемент не может существовать без родительской сущности сам по себе. В примере с формой элемент input
не может быть вне блока формы, поэтому обязательно помещаем его в блок .form
Модификатор
Модификатор — это БЭМ сущность, которая определяет вид, состояние или поведение блока или элемента. Например:
- Внешний вид: «какой размер?», «какая тема?», «какой цвет?». Размер —
size_m
. Тема —theme_dark
. Цвет —color_blue
; - Состояние —
active
,disabled
,focused
.
Модификатор отделяется от названия блока или элемента одинарным нижним подчеркиванием (_). Структура имени модификатора будет следующим:
- Для блока:
имя-блока_модификатор
- Для элемента:
имя-блока__имя-элемента_модификатор
Некоторые разработчики для отделения имени модификатора используют не одинарное нижнее подчеркивание (_), а двойной дефис (—). Я лично использую нижнее подчеркивание. Вы можете использовать то, что вам удобно, но в официальной документации используется нижнее подчеркивание.
Типы модификаторов
Модификаторы могут подразделять на типы: 1. ключ-значение; 2. булево значение.
Ключ-значение
В данном типе модификатора важно его значение, именно оно будет определять его внешний вид или состояние. Именование классов будет следующим:
- Для блока:
имя-блока_модификатор_значение
- Для элемента:
имя-блока__имя-элемента_модификатор_значение
Значение модификатора от имени отделяется (как и само имя модификатора) одинарным нижним подчеркиванием (_).
Пример
<form class="form form_bg_blue">
<input class="form__input" type="text" name="name" />
<input class="form__input" type="email" name="email" />
<input class="form__input" type="tel" name="phone" />
<input class="form__btn form__btn_size_sm" type="submit" />
</form>
Булевый
Данный модификатор используют только тогда, когда требуется само наличие модификатора, а не его значение. Например, «активно»: active
.
Пример
<ul class="menu">
<li class="menu__item menu__item_active">
<a class="menu__link" href="#">Пункт 1</a>
</li>
<li class="menu__item">
<a class="menu__link" href="#">Пункт 2</a>
</li>
<li class="menu__item">
<a class="menu__link" href="#">Пункт 3</a>
</li>
</ul>
Считается, что при наличии булевого модификатора его значение равняется true
.
Что еще предлагает технология БЭМ?
Выше перечисленное это в основном то, что я использую при верстке макетов сайта и мне этого достаточно, чтобы работа ускорилась в разы, а код был легко читаем. Но БЭМ на этом не ограничивается. Помимо именования классов в БЭМ подобным образом можно организовать и файловую структуру.
Файловая структура проекта
Суть файловой структуры состоит в том, что все файлы проекта разбиваются на блоки. В каждом блоке хранится свой набор файлов, которые необходимы для его реализации. Такой подход облегчает навигацию по файлам и позволяет включать в проект только необходимые компоненты.
Особенности:
- одному блоку соответствует одна директория;
- имя блока и имя директории совпадают, например, блок
header
— директория header/ или блокменю
— директорияmenu/
; - имена директорий элементов начинаются с двойного нижнего подчеркивания (__), например,
header/__logo/
илиheader/__form
; - имена директорий модификаторов начинаются с одинарного нижнего подчеркивания (_), например,
header/__form_bg
; - реализация элементов и модификаторов происходит в отдельных файлах и называются примерно так:
form__input.js
,form_bg_blue.sass
.
Пример
Для примера возьмем блок с формой, структура папок и файлов будет следующая:
search-form/
__input/
search-form__input.sass
search-form__input.js
__button
search-form__button.sass
search-form__button.js
_theme
search-form_theme_dark.sass
search-form_theme_white.sass
search-form.sass
search-form.js
Лично мне такой подход к разработке очень нравится. В дальнейшем хочу перейти именно на подобную структуру файлов. Естественно все файлы css и js на выходе будут объединены в общие файлы. Делается это с помощью сборщиков, например таких, как Webpack, Gulp, GruntJs и др.
Ну что ж, теперь вы имеете представление о технологии БЭМ. Повторюсь еще раз, здесь самая малая часть того, что описано в официальной документации. Не бойтесь ее читать, она написана очень доступным языком.
На этом пожалуй и завершу. Задавайте вопросы в комментариях, если таковы имеются. Чем смогу — помогу. Всем пока и до встречи в других моих постах!