Уважаемые бэмчане,
не сочтите за оффтоп, но хотелось бы услышать ваше мнение. Angular2 и Vue, например, имитируют scoped css через присваивание уникального атрибута всем тегам и добавление его же к селекторам в css. Возникла идея сделать эти трансформации приближенными к бэм методологии. Представьте, что у нашей компоненты шаблон и стили такие:
<section class='product'>
<header class='title'>
Foo
<span class='hint'></span>
</header>
</section>
.product { /* ... */ }
.product .title { /* ... */ }
.product .title .hint { /* ... */ }
Тогда пропустив шаблон и стили через наш преобразователь получим следующее:
<section class='product_ABC product'>
<header class='product_ABC__title title'>
Foo
<span class='product_ABC__title_hint hint'></span>
</header>
</section>
.product_ABC { /* ... */ }
.product_ABC__title { /* ... */ }
.product_ABC__title_hint { /* ... */ }
Принцип прост, по возможности заменить и сделать стили плоскими. Сохранить изначальный селектор Элементов и пройтись по шаблону Добавив новые имена классов. Изначально селекторы всегда вида: BLOCK(…modifiers) ELEMENT(…modifiers) … . Модификаторы мы не изменяем. В следующем примере селектор плоским сделать мы не можем, так как он зависит от состояния родителя:
.product.active .title {}
.product_ABC.active .product_ABC__title { }
Плюсы данного подхода:
- Разработка блока/компоненты не зависит от инструментария, как Css Modules, например
- Все стили после сборки под селекторами с уникальной солью - нет коллизий
- Все селекторы максимально плоские - хорошо для производительности
- Минимальная специфичность селекторов - хорошо для переопределения
- Все изначальные классы в html остаются не тронуты - если вдруг нам нужно искать элементы из js, добавлять модификаторы, или определять новые стили по этим селекторам.
Недостатки:
- Работает в компонентной архитектуре, где шаблон инкапсулирован в отдельный блок.
Дополнительно:
- Можно от соли отказаться, и гарантировать уникальность блоков самому, тогда селекторы всегда будут детерминированны.
- Можно ввести некоторые соглашения об именах на случай каких либо "edge case".
- Можно от имени блока отказаться и генерировать его другим способом, а в стилях использовать
":host"
для его стилизации.
Простите, что возможно сумбурно выразился, старался как можно компактнее подать идею. Есть ли у кого-то мысли по этому поводу?
Я так и не понял плюсов:
Не зависит от CSS Modules, но зависит от некоего кастомного преобразователя, который решает аналогичную задачу.
То ли нет коллизий и есть проблема с поиском, то ли нет проблемы с поиском, а значит есть вероятность коллизий как минимум в JS.
Следование БЭМ-методологии само по себе сохраняет плоские селекторы и минимальную специфичность в рамках разумного. Кажется, что здесь нет нужды в дополнительных инструментах (особенно учитывая богатый арсенал уже существующих решений).
Разработка самой компоненты как раз не зависит от преобразователя, это обычный шаблон и привычные стили. Лишь во время сборки приложения стили выносятся в уникальные селекторы. Css Modules решает аналогичную проблему, но половинчатым путём. Они лишь генерируют уникальные селекторы, и дают нам json с полями. А мы уже в шаблонах через интерполяцию вставляем и комбинируем эти значения. А хотелось бы, что бы кто-то из существующего арсенала, взял шаблон компоненты, стили к нему, и преобразовал всё за меня, что бы эти стили не конфликтовали со стилями других компонент. Что-то знаете из существующих решений? То, как реализовали Scoped CSS у Angular или Veu отличный пример. Но мне кажется, что эта идея не до конца развита, и если в преобразователь "добавить" щепотку бэм-а, то будет очень даже хорошо)
Например, мне не нравиться, что они добавляют эти уникальные атрибуты к каждому html элементу. A имея такой селектор:
header .title {}
, они генерируют такое в стилях:header[_ngcontent-bge-1] .title[_ngcontent-bge-1]
, а хотелось бы.myComponent__header_title
. Конечно же, их изначальная задача это симуляция scoped styles, но всё же.Именно что нет коллизий в стилях, а вот согласен, что проблемы с поиском могут быть. Но признаюсь, что у нас очень редко когда в компонентах по селекторам ищутся дом элементы (в основном всё завязано на bindings). Ну и в конце концов, идея лишь в какой-то степени добавить "полу-автоматический" бэм, а не заменить его.
Мы описываем интерфейсы в BEMJSON, разметка генерируется с помощью шаблонов. Например:
Шаблонизатор умеет из такого описания сгенерировать
Попробовать можно здесь: http://bem.github.io/bem-xjst/
Нет никакой проблемы научить шаблонизатор по такому же описанию сгенерировать какие угодно классы.
Далее. Стили мы описываем с использованием плагина для PostCSS rebem-css:
Опять-таки здесь можно без проблем генерировать такие селекторы, какие хочется. В исходниках ничего менять не потребуется.
Остается JS, который мы пишем с помощью i-bem.js. Декларация компонентов выглядит так:
При этом фреймворк предоставляет хелперы для поиска блоков и элементов, так что опять-таки, можно автоматизировать генерацию селекторов под капотом.
@tenbits А вам хочется побольше БЭМа в Ангуляр, или просто интересует, почему их подход менее гибкий?
Владимир (@tadatuta) спасибо за приведённые примеры. Согласен, БЭМ инструментарий отличная вещь, но это уже куда больше, чем просто стилизация дом элементов. В данном рассуждении я пытаюсь подойти больше с точи зрения "прогрессивного усложнения", где вначале "И был у нас простой шаблон и стили". БЭМ методология здесь отлично ложится - на эту простоту. Особенно хорошо, если у нас один большой html, с множеством блоков. Но у нас много маленьких компонент, и иногда бэм просто кажется избыточным. Иногда проще, если мы знаем что это атомарный блок, написать что-то подобное:
Пример конечно высосан из пальца, да и импортируем мы по другому, но для примера это не столь важно. Так вот, такое стилизовать можно хоть в codepen-e. Ну а после сборки шаблон и стили компонента будут выглядеть как-то так.
И ещё раз, не обязательно вдаваться в такие крайности, можно и дальше придерживаться БЭМ методологии, но скажем с какими-то поправками, зная что у нас шаблоны разбиты на компоненты и что, в конце концов, когда собираются все view, никаких конфликтов имен не будет. Поэтому вот решил поинтересоваться, или кто-то думал уже о таких "поправках" и о таком подходе?
Алексей (@zxqfox) , нет, это мы для своих нужд решили внедрить некий модульных подход для стилизации элементов. Иногда становиться сложно придумывать уникальные имена блоков(. И вот присматриваемся, кто как к этому подходит. Пока что, почти реализовали выше изложенный подход. Потихоньку будем внедрять и тестировать, посмотрим как оно придется нам по душе.