Здравствуйте.
BEM'а не должно существовать. Есть огромное количество причин не использовать эту методологию, но из-за её простоты использования и непонимания работы CSS и HTML, методология широко распространилась среди фронтендеров всего мира, в большинстве случаев среди разработчиков СНГ. Используется BEM сейчас как на больших русскоязычных проектах (Yandex, Habr), так и в некоторых фреймворках (react-md). В этой статье пойдёт подробный разбор плюсов и минусов этого подхода к разработке. Все примеры вёрстки будут взяты с официального сайта BEM.
Аббревиатура BEM — блок/элемент/модификатор. Любой макет или дизайн можно визуально разбить на блоки, к примеру — sidebar сайта. В каждом блоке могут содержаться один или несколько элементов. У элементов могут быть модификаторы состояния (active, disabled), дополнительные классы для изменения границ, ширины, цвета фона и т.д.
Идея разбития макета на блоки не новая, что нам предлагает BEM — удлинять имена классов, всегда делать элементы зависимыми от названия блока и задавать любой класс глобально. Помогает это буквально нигде и приводит к печальным последствиями в вёрстке проектов. Ниже описаны по пунктам проблемы в использовании BEM'a:
Нечитабельный html
Это вёрстка с официального сайта BEM. Удлинённые и php-подобные названия CSS классов делает любую вёрстку абсолютно нечитабельной вперемежку с атрибутами:
<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>
Ниже предоставлен образец вёрстки без наследования в имени класса названия блока, модификаторы привязываются к главному классу через наследование в SCSS, а не текстовое название класса:
<ul class="article-rewind type-static lang-ru">
<li class="next">
<div class="text">Читать далее</div>
<a class="link" href="">Основные понятия</a>
</li>
</ul>
.article-rewind {
margin: 0;
padding: 0;
list-style: none;
&.type-static {
position: relative;
display: flex;
}
&.lang-en {}
&.lang-ru {}
&.lang-uk {}
& > .next {
position: relative;
flex-grow: 1;
align-self: center;
margin-right: 88px;
text-align: right;
.text {
font-size: 16px;
position: absolute;
right: 0;
margin-top: -32px;
}
.link {
font-size: 40px;
line-height: 46px;
}
}
}
Сложности с наследованиями модификаторов
Любой класс в BEM — глобальный, и модификаторы — не исключение. Там, где CSS позволяет основному классу, например, button наследовать несколько классов active, disabled, error, вы будете задавать всё это глобально, наследуя в имени родительские имена блоков и элементов. Такой подход — игнорирование возможностей CSS как вложенность элементов в класс и удлинение имён на ровном месте:
<h1 class="article__heading_level_1 article__heading_level_1_active"></h1>
Пример наследования модификаторов через SCSS, а не через слова в имени класса:
<h1 class="heading active"></h1>
.article {
h1.heading {
font-size: 50px;
line-height: 64px;
float: left;
&.active {
color: #ccc;
}
}
}
Все классы — псевдо-глобальные
По сути, в глобальных классах нет ничего плохого. Проблема в том, что в названии класса сохраняется имя блока или элемента и использовать его вне блока уже нельзя и глобальность становится бесполезной. Плюс ко всему в браузере висят глобальные классы, к примеру promo-section_color_white который всё что делает — меняет цвет фона на белый, причём применить это можно только к блоку .promo-section. Для других блоков с белым фоном делайте новый класс с хардкодом в названии. Элементы не могут быть использованы везде в проекте, хотя и применять классы технически возможно везде:
<div class="promo-section promo-section_color_white"></div>
Вместо привязки к блоку через текст в html, можно сделать классы по-настоящему глобальным, переиспользовать на других секциях и абсолютно ничего не потерять:
<div class="promo-section background-white"></div>
.promo-section {
position: relative;
padding: 0 0 70px;
}
.background-white {
background-color: white;
}
Запрещение использования семантики
Дословная цитата из документации:
В CSS по БЭМ также не рекомендуется использовать селекторы по тегам или id
В местах, где можно с помощью mixin'a или цикла в препроцессоре воспользоваться наследованием через html-тег вы не можете этого делать:
<h1 class="article__heading article__heading_level_1"></h1>
<h2 class="article__heading article__heading_level_2"></h2>
<h3 class="article__heading article__heading_level_2"></h3>
Здесь стили можно было задать через h1,h2 и так далее, но теперь вместо ссылки на тэги мы глобально имеем заданный класс «article__heading_level_1».
<h1 class="heading"></h1>
<h2 class="heading"></h2>
<h3 class="heading"></h3>
@for $index from 1 through 6 {
h#{$index}.heading {
font-size: (42px / $index);
}
}
/* mixin output */
h1.heading {font-size: 42px;}
h2.heading {font-size: 21px;}
h3.heading {font-size: 14px;}
h4.heading {font-size: 10.5px;}
h5.heading {font-size: 8.4px;}
h6.heading {font-size: 7px;}
Подразумевает вёрстку только блоками
В каждом большом темплейте есть мелкие элементы, как кнопки, дропдауны, тайтлы, субтайтлы, секции и т.д. Но в БЭМе у вас их нету, так как любой элемент без блока использовать тоже запрещено.
Элемент — всегда часть блока и не должен использоваться отдельно от него.
Хотите дропдаун не только в хэдере? На сайте BEM'a дропдаун в header'e свёрстан как попап, лежащим в корне body. По сути, этот пункт является запрещением создания полноценного темплейта, а не чего-нибудь сложнее лэндинга.
Плюсы
Их нет. БЭМ уничтожает понятие темплейта, запрещает использование функций CSS, подталкивает разработчика к хардкоду. Буду рад похвале методологии в комментариях, будет пища для размышлений.
Автор: hirdbluebird