Нет.
Особенно это относиться к настоящему БЭМ, в котором используется специальная структура файлов, вспомогательные инструменты для компиляции проекта, вроде bem-tools, BEMHTML, borschik, setochka. В Яндексе есть в этом смысл когда вся инфраструктура заточена под этот БЭМ-фрэймворк. Есть смысл его использовать в проектах, где на разных сайтах используются одни и те же блоки. Для всего остального - нет.
На самом деле, в практике, чаще встречается выдержка из БЭМ, когда используют только синтаксис классов (.main-nav__item__descr
) и по-максимуму отказываются от каскадности в селекторах css:
.main-nav { ... }
.main-nav__item { ... }
.main-nav__item__descr { ... }
CSS обычного человека:
.main-nav { ... }
.main-nav .item { ... }
.main-nav .item .descr { ... }
После продолжительного спора обсуждения этой медологии с её сторонниками были заявлены следующие плюсы этого БЭМ-like подхода (далее просто БЭМ, для удобства):
-
Из-за особенностей парсинга css браузерами отсутствие вложенности у селекторов даёт прирост производительности;
-
Синтаксис читабельнее;
-
Не "выстрелишь себе в ногу";
-
Кросспроектное переиспользование;
-
Комфортная командная работа;
Пройдём по каждому пункту.
Я проверил на деле разницу в скорости работы селекторов. Провёл замеры парсинга css на средне-нагруженной элементами странице в которой, сначала использовался селектор #header .main-nav a
для задания красного цвета ссылки, а потом с селектором .link-class
- напрямую на эту ссылку. Да, первый вариант, с составным селектором отработал медленнее чем, второй.. на 0.01-0.015 миллисекунды. Другими словами 1000 таких селекторов дадут замедление на 10 миллисекунд. Ну не то чтобы повод волноваться, не так ли?
В своё время, в 2009 году, Виталий Харисов из Яндекса писал о скорости селекторов и было там две ссылки на страницу с 30 тысячями div'ов. В первой ссылке селекторы заканчиваются на .text и автором был отмечен рефлоу 5 секунд, а во второй селекторы заканчиваются на div и рефлоу был 37 секунд. Это был 2009 год. Сейчас эти цифры 258ms и 323ms соответственно. На сим тему производительности селекторов предлагаю считать закрытой за несостоятельностью.
Что касается читабельности, то мне совсем не понятно чем же .main-nav__item__descr
читабельнее, чем .main-nav .item .descr
или даже .homepage .main-nav li .descr
.
Зато очень хорошо понятно почему .main-nav .item:hover a
читабельнее, чем .main-nav__item:hover .main-nav__item__link
.
Оппонентом было выдвинут тезис, что в случае имени класса .main-nav__item__descr
ты сразу понимаешь всю структуру, а если использовать, например .main-nav p
то уже возникают вопросы. По моему, если тебе действительно важно показать для блока его вложенность, то ты напишешь .main-nav .item p
, как минимум. Сравнивать БЭМ с плохим css очень удобно, но это не приведёт к истине.
Тут действительно не поспоришь. Когда ты используешь селектор .main_nav__item_highlighted
переопределить его стили случайно не получиться и это защитит код. Когда используешь селектор .main-nav .item.highlighed
, то "особо одарённый" человек может ниже создать селектор .highlighed
в глобальной видимости и навредить нашему элементу меню.
БЭМ действительно, в этом плане, является пуленепробиваемым. Но цена за эту непробиваемость - время потраченное на написание длинных классов, а так же внешне усложнённый html (см. в конце документа пример). Гораздо эффективнее решить эту проблему качественным, чётким соглашением по коду в команде в котором будет предусмотрена система именования классов и использования глобальных селекторов таким образом, чтобы не было непредусмотренного переопределения. Для поддержания выполнения этого соглашения необходимо code review, но и для команд, использующих БЭМ это не менее справедливо.
В истинном БЭМе кросспроектное переиспользование это один из главных плюсов методологии. БЭМ-like синтаксис и отказ от каскадности не дают никаких плюсов в кросспроектном использовании перед обычным css.
При использовании БЭМ подразумевается, что новый человек, пришедший в команду, может изучить БЭМ и сразу начать писать в правильном стиле. И всем остальным членам команды будет комфортно от того, что у новичка тот же стиль CSS кода.
На практике всё тоже самое будет, если в команде есть чёткое соглашение по стилю кодирования. Более того, такое соглашение будет куда быстрее понято и принято, чем БЭМ.
В итоге реальные плюсы даёт только наличие методологии и стилистике кода в команде как таковой. БЭМ тут не является единственным решением. Скажем так, БЭМ - достаточно надёжное и даже пуленепробиваемое решение, но несущее за собой большую стоимость использования. Особенно учитывая минусы, о которых ниже.
В БЭМ я вижу несколько структурных минусов:
-
Много некрасивого и нечитабельного, на мой взгляд, кода, перенасыщенного символами имён классов (см. в конец документа, например);
-
Разрыв семантичной связи html и css и добавление дополнительного слоя между ними в виде плотной сетки БЭМ-классов с которыми и работает css, что, само по себе, может быть принято как плюс некоторыми людьми, но не мной - мне не нравятся лишние усложнения;
-
Практический отказ от каскадных селекторов и всех тех инструментов, которые в нём есть (
>
,+
,[attribute="..."]
,:nth-child()
и т.п.), что просто ломает всё представление о том, как писать css и, по факту, кастрирует первую 'c' в 'css' превращая 'Cascading Style Sheets' в 'Style Sheets';
Активные пользователи БЭМ сами рассказывают о некоторых частных минусах. Например, нужно чтобы несколько блоков только на главной странице вели себя иначе, чем на остальных. Без БЭМ тэгу body
ставится класс homepage
для главной, а все вложенные блоки модифицируются примерно так:
.homepage .logo { ... }
.homepage #footer .copyline { ... }
При ортодоксальном БЭМ подходе, пример c .homepage
не обойдется без модификаторов на несколько блоков. Придётся программно добавлять не один класс для body
, а свой класс модификатор для каждого блока. Такая же история будет при локализации проекта, к примеру, если надо будет сделать специфичные стили или при наличии тем оформления.
Ну или просто возникает проблема, когда нужно сделать по БЭМ что-то вот такое:
.some-block .extra-content {
display: none;
}
.some-block:hover .extra-content {
display: block;
}
Но мы её уже рассматривали выше при рассмотрении плюса "Читабельный синтаксис".
Я вижу только очень узкий фронт проектов, в которых было бы оправдано использование БЭМ. В CodeNoHito разрешается использовать БЭМ или его модификации в рамках отдельных блоков, если сможешь потом объяснить удивлёным коллегам, почему именно для этого случая БЭМ оказался лучше внутреннего соглашения команды.
А, напоследок, вот вам немного тру БЭМ кода:
<nav class="nav">
<ul class="nav__list">
<li class="nav__list-item">
<a href="" class="nav__list-item-link">Link 1</a>
<ul class="subnav">
<li class="subnav__item"><a href="" class="subnav__item-link">Link 1</a></li>
<li class="subnav__item"><a href="" class="subnav__item-link">Link 2</a></li>
<li class="subnav__item"><a href="" class="subnav__item-link">Link 3</a></li>
</ul>
</li>
<li class="nav__list-item">
<a href="" class="nav__list-item-link">Link 2</a>
<ul class="subnav">
<li class="subnav__item"><a href="" class="subnav__item-link">Link 1</a></li>
<li class="subnav__item"><a href="" class="subnav__item-link">Link 2</a></li>
<li class="subnav__item"><a href="" class="subnav__item-link">Link 3</a></li>
</ul>
</li>
<li class="nav__list-item">
<a href="" class="nav__list-item-link">Link 3</a>
<ul class="subnav">
<li class="subnav__item"><a href="" class="subnav__item-link">Link 1</a></li>
<li class="subnav__item"><a href="" class="subnav__item-link">Link 2</a></li>
<li class="subnav__item"><a href="" class="subnav__item-link">Link 3</a></li>
</ul>
</li>
</ul>
</nav>