Удобный БЭМ

u9fk769mk84qt3h2w1bikmku24k.png

Приветствую. В этой статье я расскажу, как можно изменить БЭМ, сохранив лучшие его черты и избавившись от худших.
Итак, сначала поговорим о том, что не так с БЭМ? Может, ничего не надо менять и все и так хорошо?

БЭМ — это методология, позволяющая использовать CSS/HTML/JS много раз. Она вводит понятия блока, элемента, модификатора и микса. Начав ее использовать, ты понимаешь, что это именно то, чего ты ждал много лет, это так удобно, понятно и красиво! Но спустя некоторое время начинают встречаться такие моменты в разработке, которые решить с помощью БЭМ можно, но это не приносит ни удовольствия, ни, главное, пользы. О чем я говорю? Пройдемся по таким моментам:

1. Одноразовые блоки и элементы


Данная проблема так сильно мне надоела, что заставила написать эту статью.

Понятие блока подразумевает сущность, которую можно и нужно переиспользовать, однако на практике создается большое количество блоков, которые применяются один раз.

Например, нам нужно сделать следующее: расположить на странице заголовок, за ним — текстовое поле и кнопку отправления ввода, так, как показано на картинке:

nmwmvtnjbzxro-19yxrskqrcuma.png

Что мы сделаем в соответствии с БЭМ? Есть несколько вариантов:

  1. Создать блок формы и его элементы: заголовок, кнопку, текстовое поле
  2. Создать отдельно блоки для каждого из компонентов (кнопка, текстовое поле, заголовок), а также для формы


Какой бы мы ни выбрали, у нас возникнет проблема: как задать отступы между всеми этими блоками?

Если мы выбрали первый вариант, то можно решить задать отступы для элементов формы, ведь это не противоречит методологии. Однако в этом случае мы уничтожаем суть блока: он не может быть переиспользован, так как его внутренняя разметка подойдет только к текущей ситуации.

Если бы мы выбрали второй вариант, тогда можно было бы примиксовать к форме какой-нибудь блок, а элементы этого блока примиксовать к компонентам формы. И, соответственно, для элементов только что созданного блока задать отступы. И вот тут-то и проявляется проблема одноразовых блоков: они создаются для использования только в одном месте! Их больше нельзя использовать, потому что на других страницах компоненты будут расположены по-другому.

Данная проблема порождает одноразовые блоки/элементы, а также модификаторы типа блок__элемент_size_размер или блок__элемент_place_место-где-будет-расположен-блок (для задания отступов), которые, как уже было сказано, используются один раз и загромождают как файлы разметки, так и проект собственными директориями и файлами.

То же самое касается не только отступов, но и размеров блоков (для кнопок, например, это часто тянет за собой изменение еще и line-height'ов), размеров шрифтов, внутренних отступов и т.д.

2. Длинные имена классов


Тут даже рассказывать особо не о чем. Не думаю, что кому-то нравится разметка, которая.выглядит примерно так:

Select a sector, please:


3. Значения по-умолчанию или темы блоков


Предположим, у нас есть блок кнопки. Нужно её стилизовать в соответствии с требованиями дизайна. Но в другом проекте тоже будет класс кнопки. Она будет выглядеть по-другому, однако некоторая часть стилей будет одинакова. Что советует делать БЭМ? Он говорит создать модификатор темы и задавать его всем требуемым элементам.

Но при таком подходе получится следующее:







Это загромождение кода, и это плохо.

Критикуешь — предлагай


Что я предлагаю, чтобы исправить это безобразие? Я предлагаю следующий манифест, который, по сути, является надстройкой над стандартным БЭМ.

Манифест — Improved BEM


П.1 Слой модулей и слой страницы


Я предлагаю разбить стилевое оформление на две части:

Первая часть — слой модулей (components layout). Эта часть пишется в соответствии со всеми (почти*) правилами БЭМ. Она задает стили для переиспользуемых блоков, или, лучше сказать, компонентов, например, для кнопки, текстового поля, заголовка и т.д.

Другая часть — слой страницы (page layout). Он требуется для задания стилей блоков и элементов конкретной страницы. Соответственно, эти блоки/элементы будут использованы один раз (во всяком случае, на одной странице). Здесь правила БЭМ не действуют. Выглядит это так:

Файл: index.css

.___send-button {
        margin-bottom: 2px;
        font-size: 13px;
}

.___message-textarea {
        width: 240px;
        height: 300px;
        font-size: 14px;
}


Имя файла page layout’а выбирается произвольно. Главное, чтобы оно соответствовало сути страницы. Все стили начинаются с '___', чтобы их нельзя было спутать с классами стандартных сущностей БЭМ. Также классы не привязаны к БЭМ-сущностям — их имена лишь отражают то, к чему они должны применяться. Ещё стоит заметить, что все стили page layout’а располагаются в одном файле, так как относятся к одной странице.

Данное разделение позволяет решить первую проблему, при этом не нанеся ущерба главной цели БЭМ — создания стилей/разметки так, чтобы их можно было переиспользовать. Данные стили будут применяться только на одной странице и никоим образом не будут мешать стилям компонентов из components layout. Таким образом, мы избавляемся от одноразовых классов, сохраняя возможность переиспользовать блоки и не нарушая областей видимости.

Также имеет смысл разделить components и page layout’ы и на уровне директорий.

*кроме правил, которые отменяются следующими пунктами манифеста.

П.2 Длинные имена классов


(Экспериментальный, поэтому опциональный пункт*)

Предлагается заменить часть стандартной системы именования на следующую:

Для блока: class="блок" (без изменений)
Для блока с модификатором: class="блок _модификатор" (обращение через комбинированный селектор .блок._модификатор)
Для элемента: class="блок__элемент" (без изменений)
Для элемента с модификатором: class="блок__элемент _модификатор" (обращение через .блок__элемент._модификатор)

Данный пункт позволяет получать краткий код в отношении модификаторов. Очевидно, почему нельзя сделать то же самое с элементами.

Важно, чтобы в файлах со стилями не было правил, заданных для селекторов, которые состоят только из модификаторов:

/*Неправильно!!!*/
._active {
        background-color: #abcdef;
}


*подобное именование модификаторов может привести к проблемам на блоках/элементах, смиксованных с другими блоками/элементами, при условии, что обе сущности могут иметь одинаковый модификатор. То есть, задавая модификатор для одной сущности, мы задаем его для всех примиксованных к этому узлу.

П.3 Значения по умолчанию и темы


Тут все просто. Предлагается выбрать тему по умолчанию, но прописывать стили для нее не в классе блока, который находится в файле блока, а в классе блока, который следует разместить в файле с темой. Например:

Файл — button/button.css

.button {
        cursor: pointer;
        display: inline-block;
}


Файл — button/_theme/button_theme_P2.css

.button_theme_P2,
.button {
        border-radius: 3px;
        border: 1px solid #f00;
}


Или в соответствии с п.2

.button._theme_P2,
.button {
        border-radius: 3px;
        border: 1px solid #f00;
}


Таким образом, данная тема становится стандартной, но при желании можно использовать её непосредственно.

xsmby_7zi4d4jvyd7wt_ajwjnzu.jpeg

Итог


Данный манифест призван решить некоторые проблемы, возникающие при верстке в соответствии с БЭМ. Основной его составляющей было разбиение на components layout и page layout. Хотя выглядит манифест достаточно революционно, неканонично и смело, заявленные проблемы он решает. Использовать его весь, частично или не использовать вообще — решать, конечно, вам.

P.S. Если вы сейчас гневно проскроллили всю страницу чтобы поставить минус, не забудьте написать комментарий, иначе пользы ваш минус не принесет (как и манифест).

© Habrahabr.ru