Что такое методология БЭМ
Методология разработки сайтов, от структуры проекта до модификаций отдельных элементов
Типичная верстка Яндекса, отдельные статические HTML страницы для шаблонов XSL, время когда все изображения были хаотично брошены в стандартную директорию и порядок был особо не стандартизирован. Это был далекий 2005 год, когда в компании Яндекс было зарождение методологии БЭМ, которая в 2006 была применена на первых крупных проектах, таких как музыкальный сервис и закрытая платформа для ведения блогов Я.Ру. Любой проект который требуется поддерживать в дальнейшем, необходимо грамотно организовать, чтобы не приходилось в будущем переписывать полностью и привлекать в команду новых программистов, которые с легкостью смогут разобраться в коде.
Затем в компании было принято решение делать верстку независимыми блоками, однако долго данный принцип не просуществовал и на смену ему в 2009 году пришел БЭМ, тогда еще именовавшийся Лего 2.0. Тогда и зародились основы, гласящие что блоки первичны, технологии их реализации вторичны. Цель этой статьи: понять принципы этой методологии и выявить имеет ли смысл использовать ее или это очередная промежуточная методология, которой на смену придет нечто более удобное и понятное современным разработчикам.
Что такое БЭМ?
БЭМ это аббревиатура Блок, Элемент, Модификатор. Информация о методологии в целом размещена на официальном ресурсе Bem.info, там можно найти документацию по применению, основным положениям. Так же хочу заметить тот факт, что БЭМ существует и по сей день не только на территории СНГ, но и за рубежом в крупных компаниях, таких как Яндекс, Google, BBC, Альфа-Банк, BuzzFeed, EPAM. Яндекс представляет БЭМ как «компонентный подход к веб-разработке, в основе которого лежит принцип разделения интерфейса на независимые блоки». Технология используется в основном для разработки фронтенда и несет методические рекомендации по организации проекта для длительной его поддержки. Придерживаясь стандартных правил, определенных в БЭМ вы:
- Обеспечиваете простую поддержку кода при росте проекта
- Повторное использование кода
- Точечные изменения с минимальными затратами
На сайте методологии так же есть раздел с классическими БЭМ библиотеками, подробнее с ними можно ознакомиться на сайте, сейчас мы рассмотрим главные принципы БЭМ и зачем использовать методологию в своих проектах
БЭМ HTML
Большая часть разработчиков верстки считает что БЭМ применяется лишь в HTML верстке, однако это не так. Принципы БЭМ затрагивают CSS, JavaScript, файловую структуру проекта. Рассмотрим на примерах стандартное именование всех БЭМ сущностей, начиная с HTML. Допустим я создал пустую страницу, поместив на нее блок с 3-мя элементами в которых есть иконка приложения, его название и описание. Для этого мне нужно сделать следующую структуру:
<body>
<div class="app">
<img src="app1.png" alt="Application 1" class="icon app__icon">
<h2 class="title app__title">App Name One</h2>
<p class="description app__description">Description of this application</p>
</div>
<div class="app">
<img src="app2.png" alt="Application 2" class="icon app__icon">
<h2 class="title app__title">App Name Two</h2>
<p class="description app__description">Description of this application</p>
</div>
<div class="app">
<img src="app3.png" alt="Application 3" class="icon app__icon">
<h2 class="title app__title">App Name Three</h2>
<p class="description app__description">Description of this application</p>
</div>
</body>
В данном случае мы используем принцип вложенности блоков, у каждого дочернего элемента видно его принадлежность к родительскому. Принцип повторного использования кода, 2 и 3 приложение унаследуют общий стиль определенный для первого блока. Если нам надо подсветить второй блок, мы не создаем для него другой класс, а добавляем класс модификатор:
<div class="app app_highlighted">
Если необходимо изменить не только один конкретный блок, как в предыдущем примере, необходимо использовать миксы:
<h2 class="title app__title">App Name Two</h2>
В данном случае используется app__title - микс. Изменение блока с помощью микса делается в том случае если необходимо позиционировать вложенный блок или одинаково стилизовать несколько блоков.
БЭМ CSS
Золотые правила CSS по БЭМ:
- Не использовать ID селекторы и тегов
- Минимизация вложенных селекторов
- Следовать соглашению по именованию блоков
- Указывать в модификаторах вероятные свойства, которые подвергнутся изменениям
- Разделять код на мелкие независимые части
- Использовать миксы
Следующий пример с сайта БЭМ наглядно демонстрирует использование методологии при именовании классов.
<header class="header">
<button class="header__button button button_theme_islands" />
</header>
Здесь:
- header__button - элемент блока header
- button - блок
- button_theme_islands - модификатор
Соответственно, если мы будем прописывать стиль для кнопки, мы не будем прописывать стиль button, а будем стилизовывать непосредственно сам класс .button. Так же не рекомендуется использовать совмещенный стиль тега и класс (button.button), так как при интерпретировании данного кода определенные свойства будут более значимыми и соответственно при переопределении их задача усложняется, а использование дополнительной вложенности не является хорошим тоном, как и использование !important.
Вложенность так же рекомендуется свести к минимуму, единственное где она более уместна, когда мы используем их для декорации элементов (тема оформления). Рассмотрим пример использования HTML и CSS в стиле БЭМ на примере кнопки:
<button class="button button_size_s">Кнопка</button>
.button {
font-family: Arial, sans-serif;
text-align: center;
}
.button_size_s {
font-size: 13px;
line-height: 24px;
}
.button_size_m {
font-size: 15px;
line-height: 28px;
}
Модификаторами мы меняем представление блока удобно просто и лаконично, не прибегая к дублированию большого количества кода.
БЭМ файловая структура
Все БЭМ проекты имеют схожую структуру, остается только выбрать стиль который больше подходить вашему проекту:
- nested
- flat
- flex
В nested, классической схеме для каждого блока выделяется отдельная категория, код сущностей в раздельных файлах, названия директорий элементов начинаются с символа __ а для модификаторов с _. Проект выглядит следующим образом:
project
common.blocks/ # Уровень переопределения с блоками
input/ # Директория блока input
_type/ # Директория модификатора input_type
input_type_search.css # Реализация модификатора input_type в технологии CSS
__clear/ # Директория элемента input__clear
_visible/ # Директория модификатора input__clear_visible
input__clear_visible.css # Реализация модификатора input__clear_visible в технологии CSS
input__clear.css # Реализация элемента input__clear в технологии CSS
input__clear.js # Реализация элемента input__clear в технологии JavaScript
input.css # Реализация блока input в технологии CSS
input.js # Реализация блока input в технологии JavaScript
Схема flat более упрощенная по сравнению с предыдущей, здесь директории для блоков не используются и сущности блока реализованы в отдельных файлах или в его основном файле:
project
common.blocks/
input_type_search.css # Модификатор input_type_search в технологии CSS
input_type_search.js # Модификатор input_type_search в технологии Javascript
input__clear.js # Опциональный элемент блока input
input.css
input.js
popup.css
popup.js
popup.png
Схема flex унаследовала подходы остальных двух, и теперь блоку соответствует отдельная директория, а сущность БЭМ могут быть реализованы в отдельных файлах или файлах блока.
project
common.blocks/
input/ # Директория блока input
_type/ # Директория модификатора input_type
input_type_search.css # Реализация модификатора input_type в технологии CSS
__clear/ # Директория элемента input__clear
_visible/ # Директория модификатора input__clear_visible
input__clear_visible.css # Реализация модификатора input__clear_visible в технологии CSS
input__clear.css # Реализация элемента input__clear в технологии CSS
input__clear.js # Реализация элемента input__clear в технологии JavaScript
input.css # Реализация блока input в технологии CSS
input.js # Реализация блока input в технологии JavaScript
popup/ # Директория блока popup
popup.css
popup.js
popup.png
Более предпочтительной считаю flat, так как она более логично организована и при ее использовании в проекте не появится каша, что не приведет проблемам с поддержкой проекта в будущем.
Противоречия
Очень часто читаю статьи в которых присутствует иная точка зрения на логику организации проекта. В мнениях авторов подобных статей я нахожу отражение того, что действительно подтверждает практика, а именно нечитабельный html:
<ul class="article-rewind article-rewind_type_static article-rewind_lang_ru">
<li class="article-rewind__next">
<div class="article-rewind__next-text">Читать далее</div>
<a class="article-rewind__next-link" href="">Основные понятия</a>
</li>
</ul>
Отчасти соглашусь, что это так, принципов организации допустим кода существует много, БЭМ приводит к единому стандарту. В большинстве своем БЭМ создавался не на пустом месте, ему предшествовали неупорядоченные проекты как по структуре так и непосредственно по коду, что свидетельствует об отсутствии единого стиля кода. БЭМ приводит к новому стандарту. Если взглянуть под другим углом, с точки зрения кастомизации этих блоков, тогда подход, отраженный в методологии делает это более доступным.
Я могу согласиться с тем фактом, что использование определенных в HTML5 семантических тегов является действительно полезным инструментом, но давайте посмотрим в историю. Проектирование и выпуск БЭМ был в период 2006-2010, а HTML5 стандарт, внесший семантику появился в 2014, исходя из чего можно сделать вывод, что БЭМ был спроектирован под технологии и стандарты которые были актуальны в то время.
Что касается сложностей использования с препроцессорами, не могу согласиться, так например мы можем наоборот использовать это как преимущество, допустим возьмем пример выше с тремя блоками App:
.app {
&__icon{}
&__title{}
&__description{}
}
В большинстве компаний часто используется БЭМ и к своим соискателям они предъявляют требование работать по методологии. Я использую в некоторых проектах я использую BEM организацию, иногда в файловой структуре. Выводы делать каждому свои, ну а с появлением новых стандартов и библиотек может измениться многое, главное уметь соответствовать трендам, но не забывать о базовых принципах, определенных в стандартах.