Open belozer opened 8 years ago
Мы у себя сошлись на rebem-css
+ postcss-nested
, что в итоге позволяет писать полностью валидный sass
, так что с подсветкой все хорошо во всех редакторах (и даже на github):
:block(afisha) {
padding-bottom: 40px;
color: #f2f2f2;
background: #800;
text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
&:before {
background: linear-gradient(to right, rgb(136, 0, 0), rgba(136, 0, 0, 0));
}
&:after {
background: linear-gradient(to left, rgb(136, 0, 0), rgba(136, 0, 0, 0));
}
&:elem(title) {
position: relative;
z-index: 3;
}
&:elem(movie) {
position: relative;
width: 130px;
margin-right: 9px;
padding: 5px 0 0 5px; /* In order to move 'premiere' out-of-box */
text-align: left;
vertical-align: top;
color: #fff;
&:first-child {
margin-left: 15px;
}
&:last-child {
margin-right: 20px;
}
}
&:elem(premiere) {
position: absolute;
top: 1px;
left: 0;
padding: 5px 8px;
color: rgba(0, 0, 0, 0.6);
background: #fc0;
text-shadow: none;
}
&:elem(premiere):first-letter {
text-transform: capitalize;
}
&:elem(premiere):after {
position: absolute;
left: 0;
bottom: -5px;
width: 5px;
height: 5px;
content: '';
background: 0 0 no-repeat url(afisha__premiere.svg);
}
&:elem(poster) {
width: 130px;
height: 195px;
margin-top: 1px;
}
&:elem(name) {
font-size: 17px;
line-height: 21px;
display: -webkit-box;
margin-top: 3px;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
}
&:elem(genre) {
margin-top: 4px;
color: #fff;
opacity: .5;
}
&:elem(shadow) {
position: absolute;
z-index: 2;
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none;
box-shadow: inset 0 0 80px rgba(0, 0, 0, 0.5);
}
}
Меня rebem-css
большего всего раздрожал постоянным дублированием объявления блока у элементов, когда элементы зависят от модификатора блока (или 2-х модификаторов). А в целом быстро на него перешёл. Код стал более понятным сходу.
Обновил плагин, добавил поддержку разделителя '->' модификатор -> значение специально для stylus, т.к. он запятую не так как надо обрабатывает.
:block('checkbox'):mod('theme' -> 'dark')
:elem('box')
background: #353535
border: 3px solid #ffe93b
:elem('control')
position: absolute
z-index: -1
@belozyorcev а зачем тебе stylus? В postcss есть все необходимые плагины ;)
А может быть так? (замутить плагин поверх postCss sugarSs)
.block
._mod_val
._mod2_val2
foo: bar
.block2_mod
baz: qux
Давно так хочу сделать.
@awinogradov Куча кода уже была на stylus написана. Лень переписывать. В будущем буду от него уходить.
@a-x- мало знаком с sugarSS.
Плагин работает с такими строками, которые генерируются после: postCSS nested / Stylus / Less и т.д.:
:block('bl1'):mod('mod', 'v'):mod('mod2', 'v2') :elem('elem')
:block(bl1):mod(mod v):mod(mod2 v2) :elem('elem')
.bl_mod_v.bl_mod2 .bl__elem
Думаю ещё реализовать более "чистый" синтаксис:
block('header') {
width: 100%
background: var(--color-base1)
position: relative
lost-utility: clearfix
elem('logo-box') {
lost-column: 3/12
}
elem('main').mod('list', true) {
mod('m', 'v') {
}
lost-column: 9/12
height: 110px
background: var(--color-base2)
elem('next-child') {
color: #422;
}
}
}
block('header').elem('main').mod('list', true) {
block('icon') {}
}
@belozyorcev последний вариант выглядит симпатично. если будет нормально поддерживать в том числе всякие псевдоселекторы и вложенные селекторы, то 👍. ну и кавычки для имен сущностей нужно делать опциональными, не вижу смысла их писать в CSS.
@tadatuta они опциональны. И разделитель между mod - val тоже. Может использоваться либо mod, val
, либо mod -> val
(для Stylus). Или же в стиле rebem-css - пробел mod val
upd. Мне кавычки добавляют более привычный синтаксис для моего восприятия и идентичности с BEMHTML.
По поводу псевдо-селекторов и вложенных селекторов уже на данной стадии всё работает. Эти моменты покрыты тестами. pobems v0.3.1
полностью совместим с rebem-css v0.2.0
. https://github.com/belozyorcev/pobems/blob/master/test/lib/index.js#L46
https://github.com/belozyorcev/pobems/blob/master/test/lib/index.js#L53
@a-x- SugarSS на сколько мне известно эмитирует Stylus (со слов Андрея Ситника). Значит можно попробовать так:
:block(block)
&:mod(mod val)
&:mod(mod2 val2)
foo: bar
:block(block2):mod(mod)
baz: qux
на выходе будут селекторы
.block_mod_val.block_mod2_val2
.block .block2_mod
А точно нельзя избавиться от всего этого шума :block
:elem
и сделать плагин чтобы записывать так, как я выше показал?
@a-x- можно, но это другая история. Целью данного плагина является изоляция от стиля именования блоков и добавление большей идентичности с BEMHTML, BEMTREE.
Начиная с версии 1.0.0 можно будет писать так
block(block)
mod(mod val)
mod(mod2 val2)
foo: bar
block(block2).mod(mod)
baz: qux
ну или так
block(block) {
mod(mod val) {
mod(mod2 val2) {
foo: bar
}
}
block(block2).mod(mod) {
baz: qux
}
}
или так
block('block') {
mod('mod', 'val') {
mod('mod2', 'val2') {
foo: bar
}
}
block('block2').mod('mod') {
baz: qux
}
}
и это не предел )
Также думаю над нужностью/ненужностью короткого синтаксиса.
b(block) {
m(mod, val) {
m(mod2, val2) {
foo: bar
}
}
b(block2).m(mod) {
baz: qux
}
}
Может:
.block.mod_val {
.elem.mod_val {
}
}
Или
block-name:mod-name(mod-val) {
elem-name:mod(val) {
}
}
Внесу таки 5 копеечек)
Мне кажется такой вариант оптимальным:
block('block').mod('mod', 'val') {
}
Пускай тут есть лишние ковычки, которые необязательны, но зато это легко переносить между шаблонами и стилями. Копипаст жив!)
А ещё можно моду css в bemhtml, чтобы само в файл эмитилось :)
@vithar при таком стиле могут возникнуть проблемы при парсинге, если в проекте используется что-то помимо БЭМ.
Ну для варианта, когда используется кто-то кроме БЭМ, ты уже сделал.
Я ищу наиболее лаконичный вариант писать именно BEM CSS код, чтобы он был максимально близок к валидному CSS, при этом легко читался.
Например так:
informers { /* block */
padding: 30px 0 20px;
:(size large) { /* modifier */
}
informer { /* element */
position: relative;
@tablet, @phone { /* predefined media query */
display: none;
}
:first-child { /* pseudo-class */
margin-left: 19px;
}
}
icon {
position: absolute;
}
text {
margin-top: 8px;
:(important) { /* element modifier */
font-size: 17px;
}
}
}
@awinogradov ни разу не сталкивался с необходимостью переносить селекторы из bemhtml в css и обратно.
@vithar сейчас я тебя больше понимаю.
@vithar думаю такое можно аккуратно реализовать , если скармливать плагину список блоков в проекте.
@vithar понятное дело) у тебя такой возможности не было) а теперь вот есть
Я так подумал... Синтаксис, который предложил @vithar будет прививать правильное написание стилей.
Если надо сдвинуть блок - сделай его элементом родителя и двигай в нём.
т.е. так правильней
.block2 {
width: 100px;
height: 100px;
}
.block1__item {
margin-left: -100px
}
чем
.block1 .block2 {
margin-left: -100px
}
в итоге
block1 {
item {
margin-left: -100px
}
}
объявление блока происходит только на 1-ом уровней, дальше - всё элементы.
Список блоков не надо скармливать, первый уровень — блоки.
@vithar да, я тебя просто не сразу понял.
.block1 .block2 иногда бывает надо, если надо достучаться до чего-то внутри, что ты не контролируешь в шаблонах, такой синтаксис нужен, может более вербозный, чем просто указание элеменов и других внутренностей блоков.
Можно, кстати, так
block-name another-block {
}
В смысле не пытаться вкладывать это в блок, а иметь на том же уровне. Но тут надо думать, как сделать аккуратно и нужно ли давать возможность достучаться до элементов другого блока (наверное нужно).
при склеивании селекторов получается
block1 item {}
и тут не понятно... Элемент это или блок.
Единственный вариант я вижу - это указание класса
block1 .block2
В общем про это можно думать отдельно и может даже сделать отдельный синтаксис, это же редкий кейс.
А ещё можно имена блоков с заглавной обозначать
Block1 {
item {
margin-left: -100px
}
}
Block { // .block
:active: { // .block_active
..div { //.block_active div
}
.boot { //.block_active .boot
}
}
:type:list { // .block_mod_val
item { //.block_mod_val .block__item
}
}
item { // .block__item
Block2 { //.block__item .block2
item { // .block__item .block2__item
}
}
}
}
Правда так читается более явно
block('block').mod('mod', 'val') {
}
Нет, имена сущностей должны быть консистентны в разных технологиях.
ну можно например так
block { // .block
:active: { // .block_active
..div { //.block_active div
}
.boot { //.block_active .boot
}
}
:type:list { // .block_mod_val
item { //.block_mod_val .block__item
}
}
item { // .block__item
>block2 { // .block__item .block2
item { // .block__item .block2__item
}
}
}
}
Я, конечно, и сам грешу всякими https://github.com/tadatuta/bem-indent-syntax, но не нужно экономить символы в ущерб очевидности кода и гибкости. Лень лишний раз нажать на кнопку — запилите лайв-темплейты.
Всегда ваш, горький опыт.
Скоро приступлю над разработкой версии 1.0.0.
block(bl).elem(el).mod(m v) {
mod(m2 v) {}
elem(elem2) {}
}
стоит ли добавлять в него short-syntax?
b(block) {
m(mod, val) {
m(mod2, val2) {
foo: bar
}
}
b(block2).m(mod) {
baz: qux
}
}
стоит ли добавлять в него short-syntax?
Нет, имена сущностей должны быть консистентны в разных технологиях.
@vithar Что это значит?
Чем это:
block(bl).elem(el).mod(m v) {
}
Консистентнее чем это:
block('block').mod('mod', 'val') {
}
@awinogradov синтаксис с ковычками тоже будет, просто они опциональны.
@vithar, Мне кажется, что наделять индентацию БЭМ-смыслом плохо, т.к. у неё уже есть смысл в рамках css-процессора (stylus, postcss+sugarss, etc.).
Часто будет хотеться сделать например так:
.b-page
.button2
foo: bar
.radiobox
baz: qux
Поэтому я и предлагаю так (с подчёркиваниями):
.block._mod1_val1 {
.__elem._mod2_val2 {
// ...
._mod3_val3 {
...
}
}
}
А консистентная с bemhtml форма мне тоже очень понравилась сейчас. Где-то можно будет ей пользоваться.
p.s. забегая вперёд, думаю что короткий по inv* синтаксис не постигнет судьба dsl-bemhtml, т.к. для транспиляции .block(block).elem(elem)
нужно будет примерно столько же времени, как и .block.__elem
@a-x- проблема в переносимости блоков. Многим нравится стиль Гарри Роббертса.
block-name__elem-name--mod-name
А так у всех один инструмент(шаблонизатор CSS) и в своих проектах они используют нужный им синтаксис. При этом блоки могут использоваться в проектах с историческим синтаксисом БЭМ block-name__elem-name_mod-name
и наоборот
Конвертор легко сделать
Внутри проекта вряд ли кто-то будет смешанные стили нейминга использовать
p.s. + адаптеры к будущему плагину.
@a-x- в целом выглядит интересно. Но воспринимается тяжелей. Точнее завязка идёт на синтаксисе, а не на декларациях. Визуально мыслишь классами, а не сущностями. Коротко - да, быстро - да. Но именно идея деклараций блоков теряется.
классы
.block {
.__elem {}
._mod_val {
width: 100px;
._active {
.__elem5 {}
}
}
.__elem1 {}
.__elem3 {}
}
.block__elem {
width: 10px;
._mod {
._mod2 {
._mod3 {}
}
}
}
декларации
block(block) {
elem(elem) {}
mod(mod val) {
width: 100px;
mod(active) {
elem(elem5) {}
}
}
elem(elem1) {}
elem(elem3) {}
}
block(block).elem(elem) {
width: 10px;
mod(mod) {
mod(mod2) {
mod(mod3) {}
}
}
}
@a-x- вообще в идеале сделать 2 подхода. И там уже какой победит.
А вы правда у себя в проектах используете стили на теги? А посчитайте селекторы с тегами?
но не нужно экономить символы в ущерб очевидности кода и гибкости
Я хочу легко читаемого кода в первую очередь, а не меньше символов. При этом код с & перед каждым элементом — не легкочитаемый. Синтаксис должен быть таким, что самые частые конструкции — самые простые и воспринимаемые. А всякие edge cases — возможно выразить.
Часто будет хотеться сделать например так:
.b-page .button2 foo: bar .radiobox baz: qux
Ни разу так не хочется делать. Блок описывает себя и свои элементы и в идеале не трогает другие блоки.
Всем привет. Благодаря репозиторию @tadatuta наткнулся на интересный плагин к PostCSS - rebem-css. Изначально показался он показался менее удобным, чем написание по-старинке.
Проблема 1
Подсветка синтаксиса при таком написание режет глаза...
Проблема 2
Код становится ещё длиннее... Утешает только то, что можно применять bem-naming
Проблема 3
Писали, что такой синтаксис ближе к BEMHTML. Но как по мне, он не дотягивает немного.
В итоге я решил сделать PR. В репозиторий
rebem/css
, переписав практически весь плагин. Но т.к. на слитие нужно время, а мне он нужен уже сейчас, был сделан новый плагин с расширенным функционалом на основе rebem-css.POBEMS поддерживает как синтаксис rebem-css, так и свой.
Решение 1-й проблемы
Добавлена возможность написания через кавычки
Решение 2-й проблемы
Добавлен контекст блока при объявлениях элементов и модификаторов. Теперь можно писать так
Решение 3-й проблемы
Для объявления модификаторов добавил более привычный синтаксис через запятую
:mod('mod', 'value')
Или в LESS стиле
Что дальше...
Далее часть изменений отправлю в репозиторий
rebem/css
, а в pobems буду добавлять более "горячие" нововведения. Репозиторий POBEMS