Удобный БЭМ +27





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

Итак, сначала поговорим о том, что не так с БЭМ? Может, ничего не надо менять и все и так хорошо?

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

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


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

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

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



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

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

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

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

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

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

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

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


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

<header class="section-header section-header_margin_select-sector">
        <h2 class="section-header__title font font_face_calibri-bold section-header__title_size_select-sectors">
                            Select a sector, please:
        </h2>
</header>

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


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

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

<input type="text" class="textbox textbox_theme_P2">
<button class="button button_theme_P2">Reset</button>
<button class="button button_theme_P2">Submit</button>
<button class="button button_theme_P2">Save as draft</button>

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

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


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

Манифест — 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;
}

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



Итог


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

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

Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (70):

  1. datacompboy
    /#19766250 / +2

    вообще чаще всего начинается такое не тогда, когда БЭМ плохо применим, а когда дизайн «кто в лес кто по дрова».

    откуда берутся нестандартные отступы? От неконсистентного дизайна, и пискель-перфекта без права настучать дизайнеру по голове чтоб сам следовал своим отступам.

    • VolCh
      /#19766386 / +1

      Иногда бывают задачи сделать пачку сайтов, абсолютно идентичных функционально, вплоть до общего бэкенда, но разные по дизайну.

      • datacompboy
        /#19766428

        Разные семантически или только косметически-визуально?

        Если это разные лендинги — так для них одноразовое наговнякивание штучной CSSки идеальный вариант.
        Если это разные стилизации под разные особенности — специфические CSS модификаторы протянутые через один глобальный класс на body.

        Если же они семантически разные совсем, то не факт что общий бэкенд (если только он не глупый сырой API) справится без костылей, то есть это по сути разные сайты, где реюз не всегда возможен — и только создаёт мощные стяжки из спагетти.

      • Alexufo
        /#19766884

        А в чем, собственно, проблема? Если вы возьмете готовые популярные движки типа wordpress то там как правило уже свои шаблонизаторы т.е функции которые вставляются в любую разметку. Более того, дочерние темы перекрыващие родительские функции по вкусу.

        У вас задача слышится скорее так: Как можно меньше сделать но чтобы визуально было так, как-будто бы пахали разные команды.
        В этом случае не вижу проблем больших при переопределении css, брать копию scss файлов в новый дизайн и не изменяя его структуры долбить параметры. Правда придется отслеживанием новых изменений родительской темы самостоятельно. Все еще зависит от того, на сколько считается дизайн сайта переделанным «достаточно»

        • kucheriavij
          /#19768388

          А в чем, собственно, проблема? Если вы возьмете готовые популярные движки типа wordpress то там как правило уже свои шаблонизаторы т.е функции которые вставляются в любую разметку. Более того, дочерние темы перекрыващие родительские функции по вкусу.
          В этом собственно и проблема. Шаблон должен быть шаблоном, а стили стилями. И этого не должно быть «где-то там в функции», или что еще хуже в «админке» с помощью какого-нибудь плагина, и хранится все это в базе данных. Ну и на конец, если брать конкретно wp, то на нем не надо делать что-либо сложнее личного блога…

          • Alexufo
            /#19769346

            Шаблон должен быть шаблоном, а стили стилями.
            А что по вашему входит в понятие «шаблон»? Набор дивов с перемеными, оформление которые запрещено менять кроме как через css? Если задача стоит только перекраска кнопочек да разный радиус уголков, то вопросов конечно нет.

            если брать конкретно wp, то на нем не надо делать что-либо сложнее личного блога…

            У wp самая развитая система темизации. Ей позавидовать можно. Возможность модифицировать REST API через файлы темы. Или модифицировать саму админку. Админка переходит на реакт. плагины под wp перестают писаться в ноутпадах без знания современного js. На нем как-то работает css-tricks.com
            wp сам устал от своего legacy, поэтому разрабы дружно ударились во фронтенд.

            • kucheriavij
              /#19769378

              А что по вашему входит в понятие «шаблон»? Набор дивов с перемеными, оформление которые запрещено менять кроме как через css? Если задача стоит только перекраска кнопочек да разный радиус уголков, то вопросов конечно нет.
              На мой взгляд, пользователь совсем не должен в эти вещи лезть. Хотят конструктор, пусть идут на тильду. Когда из wp делают конструктор, то это получается дикий ад для разработчика. Так что да, для меня шаблон это вьюха с разметкой, и стили в css файле. А логика должна быть там, где ей положено быть — в контроллерах
              У wp самая развитая система темизации. Возможность модифицировать REST API через файлы темы. Админка переходит на реакт. плагины под wp перестают писаться в ноутпадах без знания современного js. На нем как-то работает css-tricks.com
              только потому что у wp удобная админка, или привычная. В СНГ по этой причине все хотят битрикс. На css-triks wp наверное уже больше как фронтенд работает…

              • Alexufo
                /#19769490

                ду. Когда из wp делают конструктор, то это получается дикий ад для разработчика.

                это увы коммерция. Они последние 5 лет пилили возможности, чтобы купив тему у тебя открывалась эта самая тильда по настройке приобретенной темы. Мне тоже это было чуждо, но они работали конткретно на спрос, отказать в этом тут (удовлетворении спроса) им сложно.

                А логика должна быть там, где ей положено быть — в контроллерах

                Это спорно, когда вопрос касается cms. В cms логика лежит в ядре. (Ядро у wp мягко сказать с запашком.) Поэтому логика в файлах темы не такая уж прямо офигеть какая важная. Более значительный функционал для сайта оформляется виде плагина, так как независимо от смены темы должен оставаться. Но да, хотелось бы более серьезноо подхода чем куча хуков. Однако, имеем что имеем.
                только потому что у wp удобная админка, или привычная.

                Они сделали реклактор как у medium. Мне не знакомы никакие продукты, которые столько сил вкладывают в админку. Для меня у wp абстракция от говноядра достаточная, при работе с которым особо не пачкаешься. Бесит дико только у wp работа с ресайзами изображений. Но у учиться у wp другим есть чему.

                • kucheriavij
                  /#19769614

                  это увы коммерция. Они последние 5 лет пилили возможности, чтобы купив тему у тебя открывалась эта самая тильда по настройке приобретенной темы. Мне тоже это было чуждо, но они работали конткретно на спрос, отказать в этом тут (удовлетворении спроса) им сложно.
                  Я не против конструкторов. Но если его делать, то делать отлично, а не как плагины для wp. Но если будет конструктор из wp, то зачем сам wp? и возвращаемся к тому, что есть тильда, юкоз, и прочее, которые в этом плане обошло плагины для wp на порядки
                  Они сделали реклактор как у medium. Мне не знакомы никакие продукты, которые столько сил вкладывают в админку. Для меня у wp абстракция от говноядра достаточная, при работе с которым особо не пачкаешься. Бесит дико только у wp работа с ресайзами изображений. Но у учиться у wp другим есть чему.
                  Мне у wp только визивиг-редактор нравится. Работа со структурой не понравилась, но это мое мнение. Но сути не меняет, на крупных проектах wp берут только ради админки, а дальше скрещивают с чем угодно. Лично наблюдал прикрученный blade от ларавеля в wp, и скажу что с таким «покемоном» было намного удобней работать, нежели в его чистом виде.

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

                  • Alexufo
                    /#19769684

                    то зачем сам wp?

                    Я имел ввиду, что продаются темы, которые позволяют настраивать сами себя как tilda. Это не плагины, а функционал ядра который позволяет продавцам тем встраивать в свои темы редактор. Тут можно визуально поменять бекграунд или выбрать из коллекции. Поменять размер и цвет шрифта и т.п именно так как это заложил разраб темы. Я это не люблю так как я не продаван тем, а люди большие бабки делают на этом…
                    Работа со структурой не понравилась, но это мое мнение.

                    Ну она по своему чокнутая.
                    developer.wordpress.org/files/2014/10/Screenshot-2019-01-23-00.20.04.png
                    Но ведь именно его структура — посты(кастомные типы постов), а дальше связи между ними (теги, или теже теги с боку — категории) по сути и родят эту структуру. Это же не фреймворк. Но по этой жесткой структуре оазывается может лечь дофига чего.
                    было намного удобней работать, нежели в его чистом виде.

                    wordpress.org/plugins/blade
                    разве это не гибкость ядра, который может плагином запулить блейд?)
                    Ну по факту многие не понимают чем шаблонизатор лучше обычного php который сам шаблонизатор. Вобщем, не суть. У wp есть своя терминология не плохая и не хорошая, просто своя.

                    Пользователь не должен иметь доступ редактированию файлов шаблона, никогда, ни при каких условиях, в любой системе.

                    ну я и не утверждал этого. Можно в аминке отключить доступ к редактированию шаблонов. И будет все как говорите у wp если этого не захочет разраб.

                    define( 'DISALLOW_FILE_EDIT', true );

  2. token
    /#19766260 / +2

    Мыши плакали, кололись, но продолжали грызть кактус. Сами загоняете себя в рамки, а когда становится в них тесно, пытаетесь выкрасить другой краской, вместо того, чтобы подумать о том как сделать то же но на чистом css

    • JustDont
      /#19766286 / -2

      БЭМ — это и есть чистый цсс. Если вы уверены в другом, то вас кто-то обманул.

      • ionicman
        /#19766296 / +4

        БЭМ — это CSS без каскада — я бы не сказал, что отказавшись от главного, ради чего создавался CSS — Cascading Style Sheets, это можно было бы называть чистым CSS :D

        • dpr
          /#19766792 / -2

          Вы, как и многие, путаете понятия каскада и вложенных селекторов.
          Каскад — это свод правил, по которым определяется конечный стиль элемента.
          В БЭМ существует понятие уровней (или слоёв) переопределения, когда стили меняются или дополняются.
          Таким образом БЭМ не отказывается «от главного, ради чего создавался CSS». С каскадом там всё в порядке.

          • ionicman
            /#19766944 / +3

            Вы, как и многие, путаете понятия каскада и вложенных селекторов.
            Rly? Я понимаю под каскадом это, вложенные селекторы — это наследование, которое является одним из важнейших методов для определения стиля конечного элемента в CSS и не смотря на то, что кроме него есть еще методы, участвующие в каскаде, наследование является основой каскадирования в CSS. Жду от Вас разъяснений, где я ошибаюсь.
            В БЭМ существует понятие уровней
            Существует, но это — не CSS-каскад.
            С каскадом там всё в порядке.
            Использование CSS-каскада в БЭМ противоречит главному в этой методологии — полной независимости и отсутствия конфликтов в пространстве имен.

            Но речь, естественно, шла про CSS-каскад (масло-масляное), использование в БЭМ модификаторов и примесей вполне возможно, но ничего общего с каскадом CSS оно не имеет.

            Давай-те, чтобы говорить предметно, Вы приведете пример использования именно CSS-каскада в БЭМ, и чтобы это не противоречило правилам БЭМ?

            Еще раз — если под каскадом понимать свод правил, по которому определяется стиль элемента — то, да — можно сказать, что в БЭМ есть каскад, но это БЭМ-каскад, сильно отличающийся от CSS-каскада именно своим сводом правил.

            • dpr
              /#19767004

              Окей, каскад мы с вами понимаем одинаково. Я видимо неправильно интерпретировал вас изначально.

              Но почему уровни переопределения — это не использование каскада?
              Возьмите, чтобы далеко не ходить, пример из документации по БЭМу с кнопкой.
              Вначале стиль определен на уровне библиотеки, потом он доопределен/переопределен на уровне блоков проекта. Таким образом у кнопки есть два стиля, по правилам каскадирования браузер применит нужный. Что это, если не каскад?

            • dpr
              /#19767578

              Я сразу не заметил, или вы дописали последний абзац. Придется ответить на него, иначе в моем первом предложение возникает неточность =)

              Еще раз — если под каскадом понимать свод правил

              Это нужно понимать не «если», а именно так.

              Приведу цитату с MDN:
              The cascade is a fundamental feature of CSS. It is an algorithm defining how to combine properties values originating from different sources. It lies at the core of CSS as stressed by its name: Cascading Style Sheets.


        • yadobr
          /#19768100

          CSS создавался не ради каскада, а ради описания стилей элементов на странице, где каскад — один из вариантов реализации этого описания.

          Это все равно что утверждать, что ООП-языки создавались ради классов, а не программ, которые на них были написаны.

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

      • ArsenAbakarov
        /#19766322 / -1

        БЭМ это методология, некие соглашения и допущения, что использовать, что нет, решать вам

    • yadobr
      /#19768090

      А как указанные в статье проблемы решаются на «чистом» css? Например, переиспользуемость кода?

      *Спойлер*. Никак. Хотя многие характерны и для css.

      БЭМ — отличная вещь, которая добавляет, как минимум, компонентность и инкапсуляцию. И при использовании методологии, плюсов больше, чем минусов разработки на «чистом» css.

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

  3. ArsenAbakarov
    /#19766320

    Про темы, делается через уровни переопределения
    Про именование .block ._mod, у вас тогда будет попаболь, так у модификатора нет знания к чему он относится, вот представьте себе микс, и у блока есть мод theme и у элемента есть этот мод, и что же у вас получится?
    Стили по умолчанию, просто уровень переопределения, типа базовый уровень дизайна
    Длинные имена классов… ну я просто расширил шаблонизатор и вообще не парюсь теперь, бред это все тянуть и писать руками, я пишу {% bem_class «e:foo m:active|foo=bar» %}
    Про компоновку внутри блока и его вид на разных страницах, я просто делаю на весь блок модификатор, внутри разруливаю каскадом, да, я использую каскад, но тут он не несет проблему, да и вообще не стоит упарываться на 100%, нужно следовать логике и здравому смыслу, БЭМ не строго запрещает использовать каскад, да и в некоторых ситуациях с ним реально проще
    Внешнюю геометрию блока на разных страницах, тут я просто блоки миксую к блоку page, который висит на body, и все

  4. Klenov_s
    /#19766360

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

    • Alexufo
      /#19769510

      Я требую, чтобы все элементы просто размещенные на странице сразу выглядели в стиле сайта.

      А можно пример противоположный?

      • Klenov_s
        /#19774160

        Элемент, брошенный на странице сайта выглядит дефолтно, если он не обрамлен в какой-то задизайненный уже блок.

  5. Spaceoddity
    /#19766450

    Кто и по какой причине в качестве основного символа именования классов предложил нижнее подчёркивание? Ну это же просто жуть как неудобно. Кол-во дефисов считывается глазом на автомате. Чтобы написать нужное кол-во нижних подчёркиваний — мне придётся постоянно копипастить такие элементарные куски кода.

    Ну а по поводу БЭМ в целом, скажу что тут основная проблема не в работе фронтэндера, а в работе дизайнера. Надо чтобы дизайнер соответствовал предлагаемой методологии. Чтобы он проектировал свои интерфейсы отталкиваясь от этой концепции переиспользования блоков.
    Яндексу хорошо — у них дизайнеры интерфейсов по сути и есть разработчики. Когда всё делается по единому условному брэндбуку. Вот им и кажется что это панацея.
    В обычной жизни вы столкнётесь с кучей однотипных блоков, одни из которых будут идентичны, другие будут отличаться цветом, третьи внутренней разметкой и т.д.
    Чтобы применять этот подход — надо кучу времени потратить просто на анализ макета. Анализируя и вычленяя переиспользуемые свойства. Но извините, при таком кропотливом анализе любой подход к вёрстке будет одинаково эффективен.
    Ну не взлетает БЭМ на разовых проектах.

  6. rgs350
    /#19766466

    ИМХО, но все несколько проще чем кажется. Хотя тоже не идеально.
    Пришел к следующей схеме:
    Разделяем все наши поделки на две категории компоненты и представления.
    — Компонент (кнопки, инпуты, тул/таб-бары и т.д.) — часто мигрирует из проекта в проект, часто меняются стили.
    — Представление (реализации форм, сайдбаров и т.д.) — нужны только в конкретном проекте.
    Для первых SMACSS или его подобие. Для вторых БЭМ. Полгода. Полет нормальный.
    ЗЫ: Не знаю как это зайдет для сайтов ибо занимаюсь SPA.

  7. ilya-ivanov
    /#19766530 / +1

    1. «Одноразовый блок» вообще не стоит считать блоком. Это элемент вышестоящего блока. Если у вас форма действительно намертво связана со страницей и вы понимаете, что она не повторится нигде, то перед вами не столько .form, сколько .mypage__form. А вот блоки, ее составляющие (кнопки, инпуты, лейблы) свободно переиспользуются. Да, там может появиться каскад, но если ваш псевдоблок действительно одноразовый, то каскад в нем не может создать проблем.

    .input {}
    .my-page__form .input { /* margin, position, width, ... */ }
    .my-another-page__form .input { /* margin, position, width, ... */ }


    2. Само возникновение «одноразовых блоков» может быть следствием сырого дизайна, как выше справедливо заметили. То же самое, если часто возникает потребность в чисто декоративных модификаторах. На практике они по большей части функциональные, связанные с состояниями (_disabled, _collapsed, _invalid — такого плана). И как следствие, по большей части булевы. Если у вас много модификаторов вида «_ключ_значение», то есть смысл еще раз подумать над всей дизайн-системой, почти наверняка там не всё хорошо.

    3. Глобальные модификации стилей (темы проектов и т.п.) вводятся через уровни переопределения на этапе сборки. Если вам нужно просто стилизовать несколько похожих проектов, не надо вводить модификаторы под каждую тему) Грубо говоря, у вас есть папка «чистых» комопонентов, где зашиты общие свойства для всех проектов, и есть папки с отдельной стилизацией для каждого проекта. При сборке конкретного проекта вы берете чистый компонент и приклеиваете к нему свойства из файлов именно этого проекта.

    /* ../base/button.css */
    .button {display: block; cursor: pointer; ...}
    /* ../project-red/button.css */
    .button {background: red; ...}
    /* ../project-blue/button.css */
    .button {background: blue; ...}
    


    Никаких модификаторов тут не требуется. Индивидуальные стили проектов не надо хранить в общих компонентах. Иначе вам при 100 проектах пришлось бы в каждом блоке таскать с собой 100 модификаторов, из которых 99 не используются в текущем дизайне. Дело тут не БЭМ, а в архитектуре проектов и сборке.

    Модификаторы хороши в том случае, если у вас внутри текущего проекта есть одновременно, например, несколько разновидностей кнопок. Скажем, иконические и без иконок. Или синие для безопасных действий и красные для опасных. Вот тогда у вас могут появляться модификаторы: button_iconic, button_safe,… и т.д. Это имеет смысл, потому что они нужны все сразу в текущем проекте.

    P.S. Не то чтобы я был адвокатом или ярым фанатом БЭМ, но по факту 99% постов о «проблемах БЭМ» (в контексте именования и CSS) в итоге сводятся к тому, что автор упускает какой-то нюанс или не в полной мере понимает какую-то часть методологии. Поэтому, если возникает желание сделать свой особый БЭМ с преферансом и одалисками, то с очень большой долей вероятности что-то делаете не так.

    • datacompboy
      /#19766628 / +1

      автор упускает какой-то нюанс или не в полной мере понимает какую-то часть методологии

      звучит как классика продаж всех методологий.

    • rgs350
      /#19766702

      Подскажите, пожалуйста, как сделать следующее:
      — Вам нужно написать мегауниверсальную кнопку состояшую из иконки, текста и метки (кол-во страниц, например).
      — Иконка может быть слева/справа/вверху/внизу/нигде (наверно, модификатором придется делать).
      — Метка тоже может быть слева/справа/вверху/внизу/нигде.
      А завтра нужно будет написать элемент меню, который обладает теми же возможностями, но с другими стилями и дропдаун, в который нужно добавить стрелку которая тоже может находится слева/справа/вверху/внизу/нигде, да еще е поворачиваться на 90/180/270 градусов. Что делать блоком, что элементом и что писать в class?

      • ilya-ivanov
        /#19766952 / +3

        На мой взгляд, попытка создать «мегауниверсальную» кнопку с тысячей возможных вариаций — это и есть фундаментальная ошибка. Фактически, мы пробуем затолкать в один блок несколько десятков кнопок совершенно разного вида. Здесь автоматом должны возникнуть два вопроса:

        1. А нужны ли реально в проекте десять вариаций кнопки, не затрагивающих ее функциональные возможности? Нельзя ли как-то унифицировать?

        2. Действительно ли всё это именно кнопки? Возможно, танцы с иконками и метками намекают, что больше подошли бы другие контролы: свитчеры, селекты и т.п. Возможно, метке вообще не место на кнопке? Возможно, ее нужно вынести в лейбл?… (Просто общую логику дизайнера иллюстрирую).

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

        По крайней мере, мне пока не доводилось сталкиваться с реальной потребностью в таких мегауниверсальных кнопках. Если это существующий проект, с интересом взглянул бы на макеты.

        К слову, на хабре попадались хорошие статьи, раскрывающие суть проблемы. Например.

        • dom1n1k
          /#19767136 / +1

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

        • rgs350
          /#19767618

          Вопрос был в большей степени риторический, дающий понять, что использовать БЭМ не всегда оправдано.

          На мой взгляд, попытка создать «мегауниверсальную» кнопку с тысячей возможных вариаций

          Так-то ничего мегауниверсального кроме названия в ней нет, всего-то иконка + текст + метка. Неужели вместо одной кнопки нужно сделать пяток разных, а потом каждую из них отдельно стилизовать (они же только положением иконки/метки отличаются)?

          А нужны ли реально в проекте десять вариаций кнопки

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

          Возможно, танцы с иконками и метками намекают, что больше подошли бы другие контролы: свитчеры, селекты и т.п.

          Похоже на попытку подогнать задачу под методологию.
          Если это возможно — не вопрос, но обычно правила диктует заказчик.

          Если это существующий проект, с интересом взглянул бы на макеты.

          На самом деле проекты с таким интерфейсом вы видели и скорее всего даже используете.
          MS Office - Ribbon UI
          image

          • rgs350
            /#19776472

            Товарищ минусатор, напиши, пожалуйста, свое экспертное мнение, мне было бы интересно его узнать.

  8. bano-notit
    /#19766616

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


    1. Блоки состоят из 2 слов, называются как в БЭМ: block_name
    2. Элементы называются всегда в 1 слово: element
    3. Модификаторы выглядят как -modifer
    4. Как было сказано "page блоки" называются как l-layout_element
    5. утилитарные настройки вроде названия темы пишутся как u-utilitary

    ps Если кто-то напомнит как назывался этот стандарт, то будет вообще круто)

    • sfi0zy
      /#19766802

      Что-то похожее есть в rscss:

      1. Компоненты в 2 слова: component-name
      2. Элементы в 1 слово: element
      3. Варианты того и другого начинаются с дефиса: -variant
      4. Утилиты — с подчеркивания: _helper

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

  9. dom1n1k
    /#19767132

    <header class="section-header section-header_margin_select-sector">
            <h2 class="section-header__title font font_face_calibri-bold section-header__title_size_select-sectors">

    Конечно, будет плохая читабельность, если так накручивать и переусложнять имена классов.
    И что это за font_face_calibri-bold — это попытка скрестить БЭМ с атомарным CSS? Не надо так делать.
    И последнее: настоятельно рекомендую использовать два дефиса для отделения модификатора — читаемость улучшается кардинально, потому что бОльшую ширину отступа глаз выхватывает легче, чем разницу между '-' и '_'.

    И если переписать фрагмент примерно так:
    <header class="section-header section-header--margin-large">
            <h2 class="section-header__title text-style--h2">
    Всё выглядит гораздо приятнее.

    • wcobalt
      /#19767144

      font_face_calibri-bold дает возможность использовать шрифт calibri жирного начертания. Как можно сделать лучше и почему это плохо?

      • dom1n1k
        /#19767188

        Тем, что это несемантично. И дело тут не в какой-то абстрактной семантической теории, вопрос абсолютно практический. Сегодня у вас все заголовки набраны жирным Калибри. Завтра приходит дизайнер или заказчик и говорит — мне что-то не нравится, хочу изменить шрифт заголовков на %font-name% (ситуация ни разу не гипотетическая, всё из жизни).
        Вы будете ползать по 30 страницам переименовывать класс? Ну ок, у вас есть условный WebStorm, который будет ползать за вас, но зачем решать проблему, если ее можно просто не создавать.

        • wcobalt
          /#19767588

          Что вы можете сказать о таких проектах — это плохо или хорошо?

          • dom1n1k
            /#19767680

            Я не знаю. Я походил по репозиторию и не уловил какой-то конкретной концепции. А документация в проекте отсутствует, к сожалению. Ну ок, набор каких-то кирпичей. Но почему они именно такие, зачем, какова архитектура, какую задачу хотел решить автор?..
            Возможно, задумка автора и хороша, но без описания её трудно понять, не тратя на изучение много времени.

    • jMas
      /#19767200

      Если разбирать пример автора статьи, то вместо придумывания осмысленного названия класса (семантического), конструирование конечного вида элемента перенесли в CSS классы (признак — наличие font_face_calibri-bold ничем не лучше держать стили в атрибуте style). Если по названиям CSS классов понятно как выглядит элемент (шрифт, размер, цвет, отступы, и подобные...), то это означает, что название выбрано не правильно, да и сам человек не понимает что такое семантика. Личное мнение, что лучше использовать SCSS @include для копирования стилей в нужный блок. В осмысленно названных (семантических) селекторах гораздо проще ориентироваться, например section-header--primary, section-header--secondary, section-header--subheader.

      • dom1n1k
        /#19776920

        Личное мнение, что лучше использовать SCSS include для копирования стилей в нужный блок.
        Да, в большинстве случаев лучше именно так и поступать. Но классы-утилиты всё равно иметь приходится, иногда они тоже нужны.

        • jMas
          /#19777720

          .payments-header--primary {
              @include section-header;
              @include margin-bottom-large;
          }

          Например есть .section-header--primary (general class) и специфичное контексту место .payments-header--primary, где добавлен дополнительный отступ, добавленный миксиной (в целях демонстрации ничего не сокращал). Мое личное мнение, что классы не могут создаваться и болтаться без контекста — это происходит из-за спешки или не понимания предметной области (или не желания в ней разбираться).


          Если понадобится сменить отступ или поправить стили заголовку — редактированию будет подвержен только SCSS файл. В случае с утилитарными классами изменения отвечающие за внешний вид будут применены к шаблону и очень вероятно к SCSS файлу, что повышает вероятность возникновения конфликта (зона ответственности backend-focused разработчика может быть backend, "frontend шаблон", а frontend-focused "frontend шаблон" и scss. Снесение всего, что отвечает за стилизацию (раскрашивание элементов) в одно место — может снизить вероятность, что оба разработчика будут править одину и ту же строку шаблона.

          • dom1n1k
            /#19778708

            Не, утилитарных классов типа .section-header конечно же быть не должно. Шапка секции это вполне самостоятельная сущность, чтобы болтаться не пойми как.
            Утилитарные классы обычно нужны для добавления от одного до нескольких простых свойств — шрифт, или цвет, или отступ.

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

            Еще случай — утилитарный класс, инвертирующий блок. Меняющий фон на темный, текст на светлый и тд. Что он делает? На самом деле он просто меняет значения нескольких css-переменных. Разумеется, это решение работает не в любом контексте.

  10. Slexx1234
    /#19767314

    Нормальный дизайн, переиспользуемые классы:


    <form class="form">
        <h2 class="form__title text--left">Some title</h2>
        <textarea class="form__input" placeholder="Some placeholder"></textarea>
        <button type="submit" class="form__submit float--right">Some action</button>
    </form>

    Я не вижу проблем в вёрстке формы представленной выше, у вас разве на всех страницах кнопка разная? На одной маленькая зелёная, на другой синяя огромная, на третьей… Разве что модификаторы вроде float--right, без них не куда. Не понял а почему отступ от заголовка больше чем от поля ввода? Кто дизайн делал? Надо ещё с дизайнером пообщаться, дабы вёрстка была красивее.

    • Qumbeez
      /#19769584 / +1

      Откуда у вас появился text--left (модификатор) без элемента или блока, что за бред.

      • Alexufo
        /#19769624

        как и float--right, видимо это утилиты, аля «это мой бутстрап, бейби» с ними жесть начинается при адаптиве)

        • Slexx1234
          /#19775218

          В бутстрапе не плохо это реализовано там 100500 классов для каждого брекпоинта

          • Alexufo
            /#19780044

            100500 классов для утилит это и есть ад

            • Slexx1234
              /#19780624

              Имхо, дело привычки. Мне вот удобно

      • Slexx1234
        /#19775220

        ок,

        <h2 class="form__title text text--left">Some title</h2>
        теперь это трушный бем

  11. rgs350
    /#19767606

    Не туда.

  12. CoolWolf
    /#19767928

    Вопрос к автору. У вас на превью-картинке кусок кода с десятками тегов … вы это так серьёзно подключаете стили? Или сделали специально для статьи?

    • wcobalt
      /#19768204

      В dev-версии страницы стили подключаются именно так, при сборке все, конечно, скомпонуется в один файл. Вас не устраивает, то что, это не автоматизировано через gulp/grunt?

      • dom1n1k
        /#19769194

        И как по ощущениям, оправдывает себя политика выноса всего (вплоть до модификаторов) в отдельные файлы?
        Как по мне, это адская дробность. У меня большинство таких файлов содержали бы всего несколько строк кода. Имхо, правило «1 блок == 1 файл» это хороший компромисс между объемом файла и их количеством. Но правда, я стараюсь делать декомпозицию блоков насколько это возможно в рамках здравого смысла.

        • wcobalt
          /#19769486

          С официального сайта БЭМ «Код модификаторов и элементов также хранится в отдельных файлах блока. Такой подход позволяет подключать только те модификаторы и элементы, которые необходимы для данной реализации блока». Я всего лишь следую методологии. Но вообще, мне это тоже не нравиться, плодить десятки файлов. Хотя теоретически это полезно.

          • vithar
            /#19774706

            В отдельные файлы можно выносить не все элементы/модификаторы, а только то, что опционально. Или вообще ничего не выносить и писать всё в одном файле. Это не противоречит методологии.

      • Qumbeez
        /#19769590

        Ужасный подход. Гораздо правильнее это сделать в scss и использовать sourcemaps.

        • wcobalt
          /#19769660

          Что значит «правильнее»? Можно по существу, конкретные плюсы по сравнению с компоновкой через gulp? Семантичнее через препроцессор? Может быть

        • rgs350
          /#19776452 / +1

          Ужасный подход. Гораздо правильнее это сделать в scss и использовать sourcemaps.
          А чем правильней-то? Тем что вам так больше нравится? Какая вообще разница что происходит в dev-версии если это всех устраивает?

  13. Against-vegetables
    /#19768474

    Первый пункт.
    Как вам такой вариант:

    <form class="form">
      <div class="form__title"
        <h2 class="subtitle">Some title</h2>
      </div>
      <div class="form__elem">
        <textarea class="textarea"></textarea>
      </div>
      <div class="form__elem">
        <button class="button"></button>
      </div>
    </form>
    

    Есть блок form со своими элементами, которым мы задаем отступы. Внутри каждого элемента можно расположить любые другие блоки, но можно и замиксовать, это допустимо документацией, просто я так стараюсь не делать.

    Пункт второй.
    Длинные имена классов !== большое количество классов. А большое количество классов зачастую получается при попытке использования атомарного CSS. Лично мне, как правило, достаточно трех классов: собственно сам класс, модификатор (если нужен), класс — селектор для JS (опять же, если нужен). Если необходимо несколько модификаторов, то следует изучить возможность объединения всех необходимых в один новый.

    Третий пункт для меня не понятен.

  14. Borz
    /#19770114

    БЭМ — это методология, позволяющая использовать CSS/HTML/JS много раз

    а SSI не позволял этого делать?

  15. vithar
    /#19773774

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

    Сделайте уровень переопределения (https://ru.bem.info/methodology/key-concepts/#Уровень-переопределения) «страница» и кладите туда блоки про эту страницу (about-title, about-layout, etc). Не нужно будет изобретать отдельные правила, как вы сделали в первом пункте манифеста.

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

    github.com/bem-site/bem.info/tree/master/blocks/promo

    Они имеют отдельный префикс и не мешаются с остальными блоками сайта.

    На конкретных страницах они доопределяются:

    github.com/bem-site/bem.info/tree/master/blocks/methodology-index

    Нет ничего плохого в том, что блок используется в одном месте сайта, блоки не обязательно должны повторно использоваться где-то ещё.

  16. vithar
    /#19773776

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

    ru.bem.info/methodology/naming-convention/#Стиль-no-namespace