BEM’a не должно существовать

в 16:24, , рубрики: css
BEM'a не должно существовать - 1

Здравствуйте.

BEM'а не должно существовать. Есть огромное количество причин не использовать эту методологию, но из-за её простоты использования и непонимания работы CSS и HTML, методология широко распространилась среди фронтендеров всего мира, в большинстве случаев среди разработчиков СНГ. Используется BEM сейчас как на больших русскоязычных проектах (Yandex, Habr), так и в некоторых фреймворках (react-md). В этой статье пойдёт подробный разбор плюсов и минусов этого подхода к разработке. Все примеры вёрстки будут взяты с официального сайта BEM.

BEM'a не должно существовать - 2

Аббревиатура 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

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js