Skip to content

Latest commit

 

History

History
151 lines (96 loc) · 13.2 KB

should_we_use_bem.md

File metadata and controls

151 lines (96 loc) · 13.2 KB

Стоит ли использовать БЭМ

Нет.

Особенно это относиться к настоящему БЭМ, в котором используется специальная структура файлов, вспомогательные инструменты для компиляции проекта, вроде 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 подхода (далее просто БЭМ, для удобства):

  1. Из-за особенностей парсинга css браузерами отсутствие вложенности у селекторов даёт прирост производительности;

  2. Синтаксис читабельнее;

  3. Не "выстрелишь себе в ногу";

  4. Кросспроектное переиспользование;

  5. Комфортная командная работа;

Пройдём по каждому пункту.

Производительность селекторов

Я проверил на деле разницу в скорости работы селекторов. Провёл замеры парсинга 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>