Open tadatuta opened 9 years ago
Даже не знаю, напоминает ли этот текст мне что-то или нет...
Я подробнее хотел бы почитать про тему «БЭМ — это не только про CSS» :)
Тогда это можно представить как служебный «приватный» блок.
Можно уточнить что это за «приватный» блок и как это выглядит в коде?
Можно уточнить что это за «приватный» блок и как это выглядит в коде?
Принципиально отличий нет. Примером такого блока в bem-components является menu-item — он не имеет смысла без menu
, но сам по себе достаточно сложный, чтобы вынести его в отдельный блок.
При желании можно ввести какой-нибудь префикс, чтобы отличать такие блоки.
@voischev и про это напишем обязательно
Опечатка в примере про каскад: .nav__hover
=> .nav_hover
Можно еще написать, что: 1) элементы не должны болтаться в дереве на пределами родителя (когда, например, к блоку миксуются чужие элементы) 2) не должно быть классов, где блок указан только с модификатором (пример: https://github.com/crushlovely/skyline/blob/master/example-forms.html#L96)
@mishanga
Опечатка в примере про каскад:
.nav__hover
=>.nav_hover
Исправил, спасибо!
Пост дополню.
Как обещал, дополняю про block__el__el
:
Если вам нужно сделать элемент у элемента, значит вам нужно создать новый блок или сделать ваше BEM-дерево с одинарной вложенностью элементов! Вместо:
<div class='block'>
<div class='block__elem1'>
<div class='block__elem1__elem2'></div>
</div>
</div>
Есть два варианта:
№1. Бить на блоки: делать новый блок
<div class='block1'>
<div class='block2'>
<div class='block2__elem'></div>
</div>
</div>
№2. Рубить ветки у вашего BEM-дерева: делать BEM-дерево с 1-ой вложенностью элементов
<div class='block1'>
<div class='block1__elem1'>
<div class='block1__elem2'></div>
</div>
</div>
Типичная ошибка:
Попытка вложить имя элемента в имя блока.
Чтоб "схитрить" и "как-будто не вложить", написать не block__el1__el2
а blockel1__el2
или block__el1el2
. Так нельзя.
/* Так писать нельзя! */
.block {}
.blockel1 {}
.blockel1__el2 {}
Будут проблемы при переносе
<!-- попытались перенести в другое место - получили элемент что завис "в воздухе" без блока-родителя -->
<div class='someblock'>
<div class='blockel1__el2'></div>
</div>
Такие имена можно делать только если .blockelem сохранит логический смысл при переносе в другой блок.
Обратите внимание - вы не можете вкладывать элементы в элементы в CSS, но можете и должны вкладывать элементы в элементы в HTML! DOM-дерево и BEM-дерево могут быть разными.
БЭМ-дерево на то и дерево, что поддерживает вложенность, поэтому в БЭМ-дереве, разумеется, разрешается вкладывать элементы в элементы, блоки в блоки, блоки в элементы. Запрет есть исключительно про нейминг.
element__element
нельзя в CSS, но можно в HTML!
@delka Во втором примере потерялась чиселка возле имени блока.
Еще есть претензия к последнему абзацу. БЭМ-дерево на то и дерево, что поддерживает вложенность, поэтому в БЭМ-дереве, разумеется, разрешается вкладывать элементы в элементы, блоки в блоки, блоки в элементы. Запрет есть исключительно про нейминг.
@tadatuta Поправил бы ;-) Ты ж овнер!
@tadatuta спасибо, отредактировал и дополнил коммент твоим чтоб было понятней. Заодно и слайды доклада обновил: http://delka.github.io/talks/wsd/2014/bem/
@mishanga: 1) элементы не должны болтаться в дереве на пределами родителя (когда, например, к блоку миксуются чужие элементы) Элементы могут находится в DOM за пределами своего блока: https://web-standards.slack.com/archives/bem/p1477471042000233
@tadatuta А как к вам в бэмовый slack попасть?
@kompolom просто регишся под своим мылом тут: https://web-standards.slack.com/messages/bem/ Там доступ открыт для всех.
По мотивам обсуждения в твиттере с подачи @delaz, решили написать пост и собрать еще вопросов и тем для разъяснения, которые в будущем планируем добавить в раздел про методологию.
Что у нас получилось?
Пойдем по порядку, а вы задавайте вопросы или дополняйте список в комментариях. Ответы будем выносить в пост.
«БЭМ — это длинные имена классов. b-button — это длинно!»
Отвечаем: БЭМ не навязывает префиксы. Чтобы писать хорошо поддерживаемый и реиспользуемый код, префиксы совершенно не нужны. Исторически они появились в переходный период для того, чтобы отличать новый код, написаный по БЭМ, от старого. Со временем мы от них отказались. Если посмотреть в код, можно увидеть, что префиксов там нет.
«А как же префикс js- или i- для блоков без визуального представления?»
Когда-то можно было сверстать сайт практически без JS-кода. Сейчас большая часть блоков имеет JS-представление. Глядя на текущую ситуацию мы поняли, что нет нужды как-то отличать технологии реализации блока на уровне нейминга. Посмотрите, к примеру, на Web Components. Объективно необходимости в префиксах нет, но каждый волен выбирать, что ему, проекту или команде удобнее и/или привычнее.
«Префиксы — ладно. А просто длинные названия блоков?»
В этом и похожих случаях вы можете использовать классы типа
btn
вместоbutton
. Это никак не помешает вам разрабатывать по БЭМ. Все как с названием переменных в JS:context
,ctx
илиc
. Но помните, вам, вашим коллегам и тем, кто будет разрабатывать и поддерживать проект после вас это предстоит читать, понимать и с этим работать ;)Остается вопрос про неймспейсы — мы пишем имя блока перед именем элементов (
button__icon
) и модификаторов (button_active
).Если декомпозировать «проблему», можно выделить 2 потенциальных минуса:
gzip
, который отлично жмет повторяющиеся последовательности и сводит минус на нет.И тогда, благодаря неймспейсам, будет решено следующее:
active
(на что повлияет этот класс?) VS.input_active
илиitem
VS.nav__item
.«Что вы скажете на
nav__item__link
? Все равно длинно»Да. И к тому же не по БЭМу :)
Неймспейсом служит только имя блока. А отражать вложенность в именах элементов не нужно. Это не только длинно, но еще и не позволит при повторном использовании блока в другой ситуации (или просто при рефакторинге) легко вынуть один элемент из другого. Плоская структура касается не только нейминга, но и расположения кода на файловой системе:
Для выражения вложенности вполне достаточно DOM-дерева:
«Логично. Как отличить — делать блок или элемент? Например,
nav__link
— это элемент меню или самостоятельный блокlink
, который будет использоваться и в других местах на странице?»Тут нам на помощь приходят миксы — возможность смешать на одном DOM-узле несколько блоков (или элементов/модификаторов) одновременно.
Предыдущий пример вполне может выглядеть так:
При этом все общее, что есть у всех ссылок на проекте, будет описано в блоке
link
, а особенности, присущие только ссылке внутриnav
— дляnav__link
.«Почему нельзя стилизовать ссылки каскадом через
.nav__item .link
?»nav__item
совсем исчезнуть.«Получается, что в каскадных таблицах стилей нельзя использовать каскад?»
Можно. Но нужно понимать, какие последствия это влечет. Например, каскад уместен, чтобы менять элементы в зависимости от состояния блока (
.nav_hover .nav__link { text-decoration: underline; }
) или, скажем, темы (.nav_theme_islands .nav__item { line-height: 1.5; }
).Но в случае использования каскада вы рискуете повысить связанность кода и сделать его реиспользование невозможным, что в будущем может привести к ситуации, когда переписать проще, чем исправить.
«Как в принципе отличать, где блок, а где элемент?»
Если хочется переиспользовать кусок кода вне контекста родителя — это точно блок. Если кусок кода не имеет смысла без родителя — это скорее всего элемент. Аналогией служит Shadow DOM в Web Components.
Исключением может быть ситуация, когда у такого элемента оказывается слишком богатый внутренний мир и возникает желание сделать его собственные элементы. Тогда это можно представить как служебный «приватный» блок.
Что скажете? Наши ответы помогут вам разобраться в ваших ситуациях или же нам стоит подумать над чем-то еще? Будет очень здорово получить от вас вопросы или же примеры, которые мы сможем объяснить. А потом вынести всю эту полезную информацию в раздел сайта.
Очень ждем ваших комментариев!