Методология БЭМ (BEM)
БЭМ
, это методология, разработанная Яндексом для ускорения разработки, читаемости и повторного использования HTML/CSS
кода. В её основе лежит принцип разделения интерфейса на сущности:
- Блок — это строительный кирпичик интерфейса, базовый компонент страницы, например, кнопка или форма. Блоки обеспечивают независимость, так как могут быть повторно использованы в разных частях проекта без изменения своих свойств. Блоки именуются таким образом, чтобы их название отражало их функцию, например,
button
для кнопок - Элемент — это составная часть блока, которая выполняет определенную функцию. Элементы существуют только в контексте блока и не могут быть использованы отдельно от него. Например, в блоке
form
, элемент может бытьinput
для поля ввода. Именование элементов обычно происходит через двойное подчеркивание после имени блока, напримерform__input
- Модификатор — это свойство, которое изменяет внешний вид или поведение блока или элемента. Это может быть отличительный цвет, размер или состояние, такое как
active
илиdisabled
для кнопки. Модификаторы именуются с использованием одного подчеркивания после имени блока или элемента, напримерbuttondisabled
илиform__inputlarge
Основные соглашение
- Разрешено использовать только классы, нельзя именовать блоки через
id
- Классы пишутся в нижнем регистре. Если класс состоит из нескольких слов, то их нужно разделять дефисом
-
, напримерmain-menu
- Нельзя стилизовать элементы каскадом, например:
.main-menu__item .link
, а также использовать названия элементов.main-menu__item a
Пример разметки по БЭМ:
<ul class="main-menu">
<li class="main-menu__item">
<a class="main-menu__link main-menu__link--active" href="#1">Пункт 1</a>
</li>
<li class="main-menu__item">
<a class="main-menu__link" href="#2">Пункт 2</a>
</li>
<li class="main-menu__item">
<a class="main-menu__link" href="#3">Пункт 3</a>
</li>
</ul>
Блок
Независимый компонент страницы, который может быть повторно использован. Основные отличия блока:
- Блок полностью независим, при перемещении в другое место на странице не теряет своей самодостаточности
- Блок не должен влиять на свое окружение, нет внешних отступов
margin
иposition
- Блоки можно вкладывать друг в друга
Наименование блоков
Имена блоков характеризуют смысл и отвечают на вопрос, что это? — логотип, меню, форма.
<!-- Блок main-menu -->
<ul class="main-menu">
...
</ul>
Наименование оберток
При именовании оберток в методологии БЭМ нужно учитывать контекст.
Если расположение оберток повторяется и может использоваться в разных местах, то лучше использовать общее название класса, например grid
или container
. Такой подход позволяет применять обёртку в нескольких местах, так как она не ограничена семантическим значением.
Если расположение оберток уникально для группы блоков, то стоит использовать название класса, связанное с блоками, которые позиционируются. Например, если нужен класс обертки для группы блоков main-menu
, подойдёт название main-menu__wrapper
.
<!-- Блок main-menu -->
<ul class="main-menu">
<div class="main-menu__wrapper">
...
</div>
</ul>
Элемент
Часть блока, которая не может использоваться в отрыве от него.
Наименование элементов
Имена элементов характеризуют смысл и отвечают на вопрос, что это? — пункт меню, ссылка.
Имя элемента должно начинаться с названия блока и заканчиваться названием элемента, которое пишется через разделитель __
.
<!-- Блок main-menu -->
<ul class="main-menu">
<!-- Элемент main-menu__item -->
<li class="main-menu__item">
<!-- Элемент main-menu__link -->
<a class="main-menu__link" href="#1">Пункт 1</a>
</li>
...
</ul>
Элементы можно вкладывать друг в друга, но в названии нельзя прописывать иерархию, например: main-menu__item_link
.
Модификатор
Сущность, определяющая внешний вид, состояние или поведение блока, или элемента.
Наименование модификаторов
Название модификатора характеризует внешний вид или состояние, какой цвет? — красный, выделенный и т.д.
Имя модификатора отделяется от имени блока или элемента, двумя дифисами --
<!-- Блок main-menu -->
<ul class="main-menu">
<!-- Элемент main-menu__item -->
<li class="main-menu__item">
<!-- Элемент main-menu__link с модификатором main-menu__link--active -->
<a class="main-menu__link main-menu__link--active" href="#1">Пункт 1</a>
</li>
...
</ul>
Модификатор нельзя использовать в отрыве от модифицируемого блока или элемента.
Миксы
Прием, позволяющий использовать разные БЭМ-сущности на одном DOM-узле без дублирования кода:
<!-- Блок main-menu -->
<ul class="main-menu">
<!-- Элемент main-menu__item -->
<li class="main-menu__item">
<!-- Элемент main-menu__link и блок button -->
<a class="main-menu__link button" href="#1">Пункт 1</a>
</li>
...
</ul>
Префиксы
Иногда в названиях классов используют префексы, можно обойтись без них, для самого БЭМ они не нужны, но для облегчения восприятия, полезно использовать.
b (блок)
помогают реализовать пространства имёнl (layout)
используется для выделения лайаутных блоков, которые используются для позиционирования, ширины и т.д.g (global)
префикс для глобальных классовjs
только для навешивания JS-обработчиков, для таких классов нельзя писать стили
SASS
Для блока:
<!-- Блок main-menu -->
<ul class="main-menu">
<!-- Элемент main-menu__item -->
<li class="main-menu__item">
<!-- Элемент main-menu__link и блок button -->
<a class="main-menu__link button" href="#1">Пункт 1</a>
</li>
...
</ul>
Стили будут следующие:
.main-menu {
&__item { }
&__link { }
}
Важно понимать, если использовать плоскую структуру без каскада, значит все будет понятно и легко поддерживать код.
Еще пример правильного именования классов:
.main-menu { }
.main-menu__item { }
.main-menu__link { }
@media
Стили для мобильных, пишутся внутри блоков и элементов. Код должен быть написан так, чтобы мы могли скопировать CSS-код блока, вставить его в другой проект и все заработает. Не нужно их разносить по разным местам.
Медиа-запросы, написанные внутри блоков и элементов обеспечат поддерживаемый, не повторяющийся код:
.main-menu {
font-size: 16px;
&__item {
width: 768px;
// все стили для блока в одном месте
@media @large {
width: 1200px;
margin: 0 auto;
}
}
}
Файловая структура
Придерживаться рекомендуемой файловой структуры не обязательно.
При использовании на проекте сборщиков, например Webpack
каждый блок хранится в своей отдельной директории/файле, один блок — одна директория. В неё помещаются изображения и скрипты данного блока.
Такая файловая структура позволяет легко поддерживать и повторно использовать код:
-
-
-
img
изображения БЭМ-блокаmain-menu.less
стили БЭМ-блокаmain-menu.js
скрипты БЭМ-блока
-
-