BEM с человеческим лицом

Звучная аббревиатура BEM пришла к нам из лабораторий Яндекса. Там, как и в случае с XSLT, применение BEM решили возвести в абсолют: под BEM’ом в Яндексе понимают целое семейство утилит и подходов, объединенных единой идеологией блочной архитектуры веб-приложений. Как любая тоталитарная система, BEM требует соблюдения строгих правил при разработке, не редко вступающих в конфликт со здравым смыслом небольших проектов, не сравнимых по ресурсам с Яндексом. И да, то самое чувство, когда читаешь официальные доки по BEM.

Однако, как часто бывает в процессе эволюции больших систем, под давлением интеллекта и безлимитных сроков рождается технологический алмаз, настолько же маленький и самостоятельный, насколько и ценный, который огранят уже другие. Да, BEM с его спасительной строгостью — это явное откровение. Каждый, кто на моих глазах причащался, мнгновенно становился счастливым. Однако, после первой волны наслаждения приходит осознание, что второй подход к этому снаряду может порвать ментальные связки по всему объему мозга. И вот уже слышны жалобы на слишком большую сложность освоения, на чрезмерную многословность, на (внимание!) увеличение количества мегабайт в HTML и CSS, и кто знает на что еще, не относящееся к делу.

Соглашусь, трудно взять и начать писать BEM без разбега: и нотация глаз колет, и старые трюки не проходят, и думать приходится системно. И вообще, писали как-то годами без BEM’а и писать будем! А ведь для легкого и непринужденного преодоления порога вхождения нужно сделать всего два движения. Во-первых, понизить сам порог, смягчив BEM. И во-вторых, немного подтянуться самим. Тогда переход будет ровненьким и мы мягко вкатимся в эру читабельного и поддерживаемого CSS.


Как всегда, напоминаю, что если у вас нет никаких проблем с поддержкой CSS, то мы, юродивые BEMщики, завистливо просим вас смилостивиться и смело считать статью бредом, чушью, ересью, булшитом, графоманством и технологией ради технологии. Остальных же, завязших в зовущих гибкостях CSS прошу набраться терпения и следовать за мной.

Немного контекста нам не помешает, особенно исторического. Чтобы лучше понять куда нас ведет BEM, стоит сначала вспомнить, откуда мы идём. Итак, коротко приведу этапы становления стиля написания CSS.

1995: Доисторическая эра

<font color="red">


Данные и представление перемешаны, невозможно взять и поменять цвет всех заголовков, удельный вес информации крайне низок. А если еще вспомнить таблицы и порезанные картинки, то даже шестой эксплорер — торт! Но всё это пока не является проблемой, успешные сайты дают такую отдачу, что их можно писать хоть на ассемблере.

2000: Примитивизм

h3 { color: red }


Ура, можно взять и всё перекрасить одной правкой. Раскладка всё еще делается таблицами, но уже подкрадываются флоаты. Пузырь доткомов лопнул, пора подумать об эффективности и поддержке.

2005: Мы умеем в селекторы!

div p.red h3 { color: red }


Вот оно, зарево того пожара, в хаосе которого многие из нас сгорают на работе и по сей день. Тогда сайты уже умели делать не только студенты технических вузов, но и матёрые системные программисты. Они развивали фреймворки для бекенда, правильно проектировали базы данных, учились держать нагрузку, и даже создавали nginx! Но при этом совсем не умели и не хотели уметь CSS, или, тем более, этот ваш мерзкий JavaScript. Это привело к Bootstrap и jQuery.

2007: Семантический CSS

.article.new .title { color: red }


В тред заядлых бэкендеров врывается pepelsbey и несет доброе, светлое, чистое. Избавляет от тегов в CSS, открывает глаза на значение оных в HTML, вдохновляет на здоровый образ мысли и кода во фронтенде. Больше микроформатов и хорошего, годного веба, как его задумывал создатель.

2010: Назад в каменный век вместе с Twitter Blueprint


Да, много добрых дел натворили наши товарищи, всерьёз принявшие Bootstrap за фреймворк не только для админок. В то время интернет растет экспоненциально, любые рабочие решения копируются не глядя, ведь надо успевать за конкурентами клепающими такое же добро. Какая еще поддержка — лишь бы свой фейсбук успеть запилить!

2015: BEM

.article__header--new { color: red }


Оттягивали-оттягивали маятник в сторону быстрого старта и дооттягивались: в лоб прилетел жесткий до жестокости BEM. Пристыженные своей былой распущенностью мы готовы с головой броситься в терновый куст вычурного синтаксиса, лишь бы прикрыться могучим авторитетом и снова не думать про свой CSS.

Основные перегибы: глобальных стилей не иметь, всё-при-всё упаковывать в элементы, к другим методологиям в глазки не заглядывать, свой HTML руками не трогать, чужой CSS домой не приводить. С таким строгим воздержанием и кодить сесть не встанешь.


Что главное нам надо от BEM’а:

  1. Отсутствие коллизий
  2. Отсутствие коллизий
  3. И еще раз отсутствие коллизий


BEM гарантирует отсутствие коллизий с помощью изоляции через пространства имён. Старая добрая концепция изолированных модулей. А с SASS вообще целый ООП. Конечно, сначала надо хорошенько подумать над разбиением на компоненты, но сперва давайте порадуемся дарам модульности:

  1. Читаемый и поддерживаемый код
  2. Переиспользование компонентов
  3. Простота тестирования
  4. Гармония с объектной природой JavaScript


Вот и всё. Если нам удасться сохранить главную ценность BEM’а — изоляцию компонентом, то творить внутри самих компонентов можно будет всё что угодно. Если вы контролируете все корневые стили, то есть у вас весь-весь код разбит на пространства имён, и за их пределами селекторов нет, то вы достигли просветления и можете позволить себе всё.
Как же можно очеловечить BEM? А очень просто: надо немного расслабиться, вернуться к здравому смыслу и вспомнить чувство фана от экспериментов. От простого к сложному, от очевидного к интригующему.

Развидеть двойное подчеркивание


CamelCase нотация для блоков радует глаз заядлых си-плюс-плюсщиков/яваскриптистов/рубистов, а еще помогает никогда не путать блоки и элементы.

.Article { … }
.Article-title { color: red }


Еще чуть-чуть и станет совсем похоже на сексуальный рубёвый DSL.

Лаконичные модификаторы


Если следовать правилу «никогда не нарушать границы пространств имён» и каждому блоку выделять по отдельному элементу, то есть вместо двух классов на ноду:


делать две ноды на два класса:


то можно упростить именование модификаторов до привычных:

.Article.new { … }


А если добавить им префикс is-, то стили можно прямо читать вслух:

.Article.is-new { … }


Дело, конечно, не за префиксами модификаторов, это всего-лишь приятный бонус. Главное, что у блоков Box и Article не будет конфликтов даже если захотеть, и не придется ловить баги от того, что иногда модуль Article загружается раньше модуля Box и его стили получают другой приоритет. Но это и так очевидно же!

Каскадность


Можно вернуть в ваш BEM немного CSS:

.Article.is-new .Article-title { color: red }


Радует то, что дальше одинарного вложения BEM вас никак не пустит по определению (не повторять структуру HTML-дерева), так что такое уже невозможно:

.Article .Article-title .Article-name { … }


И конечно, совсем нельзя вмешиваться в чужое пространство имен:

.Article .SubmitButton .Icon { … }


Иногда, по старой плохой привычке очень-очень хочется так сделать. Но нельзя. Баланс с хаосом надо держать, а иначе вы нарушите основу целостности BEM’а и все старания пойдут насмарку.

Не использовать BEM


Да, если на проекте всегда использовать BEM, то иногда можно BEM не использовать. В листовых компонентах можно использовать CSS свободной формы, не следуя никаким принципам BEM’а. Достаточно упаковать такой «непослушный» код в его собственный блок-изолятор и можно писать так:

.WYSIWYG {
  h1 { … }
  p { … }
  ul li { … }
}


Строгая культура других модулей не позволит им вмешаться во внутренние дела модуля WYSIWYG и всё будет хорошо. Конечно, вложить какой-то еще компонент в «непослушный» компонент не получится без вероятности коллизий, так что такие «непослушные» блоки могут быть только листьями в дереве компонентов: их можно вкладывать в любые компоненты, но не любые компоненты можно вкладывать в них.

Такой трюк бывает полезен не только в случае встраивания непредсказуемого пользовательского контента. Любой jQuery-плагин легко оборачивается в блок-изолятор и не благоухает своим CSS на всю страницу. Еще встречаются ну очень большие компоненты, например табличные таблицы в таблице таблиц, где строгое следование BEM’у заживо похоронит верстальщика под гнетом префиксов, так что дешевле всунуть Bootstrap. А еще случаются сложные формы, которые тоже удобнее и быстрее сделать листовыми элементами в блоках-изоляторах, а потом уже думать.

Базовые стили


Имеются ввиду размер шрифта, интерлиньяж, цвет ссылок, булиты списков и прочий reset/normilize.css. Большую часть наследуемых стилей возможно экранировать только с помощью жесткого переопределения всех этих стилей для каждого контейнера. Это выглядит излишним для всех, кто не планирует завоевать мир своей универсальной библиотекой абсолютно переносимых компонентов. Иногда, полезнее смириться с несовершенством текстового веба, чем тратить силы на борьбу с ветряными мельницами.

Приняв это, становится очевидно, что старый добрый SMACSS подход к разделению стилей отлично портируется на BEM. Базовые стили остаются как есть. Layout становится просто специальным нелистовым компонентом. Модули, они же компоненты, они же блоки. Состояния проецируются на модификаторы один в один. Поддержка тем в BEM’е как бы вообще нативная. А состоянием в современном приложении должна управлять доменная логика и потом рендерить модель через React (руки прочь от jQuery!).


И вот уже стало всё знакомо и совсем не страшно. Можно даже сказать, что BEM с человеческим лицом — это старый добрый CSS для семантически правильного HTML, только легче поддерживается, проще пишется, лучше сжимается и быстрее исполняется.

Голый BEM — это прокрустово ложе, но если его понять, принять и допилить, то он становится сиденьем истребителя — тесновато, но зато на нем можно летать!

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

© Habrahabr.ru