Комментарии 54
никак не мог найти ответ на вопрос, а как можно прикрутить bem-tools на проект без использования BEMHTML шаблонизатора, и использовать привычный html, подтолкните хотя бы куда копать
НЛО прилетело и опубликовало эту надпись здесь
Для простой сборки БЭМ-проекта можете попробовать grunt-bemaker.
Спасибо автору! Отличная статья. Обязательна к прочтению всем сомневающимся.
Когда читаю про БЭМ, всегда мучает вопрос: почему вы выбрали схему «A B», а не «A > B»? Ведь тогда не требовалась бы сборка проекта, да и css вполне читабелен был бы.
можно подробнее о том, про какую схему идёт речь?
Не совсем про схему, про селектор css ">"
К примеру:
.blockX { }
.blockX > .item { }
.blockX > .item > .something { }
А не:
.blockX { }
.blockX__item { }
.blockX__something { }
В первом варианте сразу видно какой элемент в какой вложен, во втором между.blockX и .blockX__something может быть куча слоев, то есть css, по сути, не отображает структуру html.
К примеру:
.blockX { }
.blockX > .item { }
.blockX > .item > .something { }
А не:
.blockX { }
.blockX__item { }
.blockX__something { }
В первом варианте сразу видно какой элемент в какой вложен, во втором между.blockX и .blockX__something может быть куча слоев, то есть css, по сути, не отображает структуру html.
Понятно. Есть несколько причин (о некоторых из них я написал в этой статье, кстати):
1. Миксы. Очень часто надо «смешать» несколько БЭМ-элементов на одной ноде, и если нет префиксов и имя элемента не содержит имени блока, совершенно неясно, какой элемент к какому блоку относится.
2. Работа с BEM из JavaScript. Удобно получать готовую ссылку на элемент по имени класса, а не делать вложенный поиск по селекторам.
3. Вес (специфичность) селекторов и возможности переопределения и доопределения стилей. У селектора
4. Гибкость HTML. В БЭМ вообще не очень приветствуется, если элементы и их отображение сильно зависят от структуры. Обойтись без этого сложно, но специально фиксировать, что элемент — прямой потомок (селектор
Кстати, БЭМ не должен отображать структуру HTML :) Его задача — перевести DOM-дерево в BEM-дерево, наложив сверху CSS-классы как overlay, и структура при этом возникает новая.
1. Миксы. Очень часто надо «смешать» несколько БЭМ-элементов на одной ноде, и если нет префиксов и имя элемента не содержит имени блока, совершенно неясно, какой элемент к какому блоку относится.
2. Работа с BEM из JavaScript. Удобно получать готовую ссылку на элемент по имени класса, а не делать вложенный поиск по селекторам.
3. Вес (специфичность) селекторов и возможности переопределения и доопределения стилей. У селектора
.block > .elem1 > .elem2
иной вес, чем у .block__elem2
, переопределить его можно только через селектор такого же веса.4. Гибкость HTML. В БЭМ вообще не очень приветствуется, если элементы и их отображение сильно зависят от структуры. Обойтись без этого сложно, но специально фиксировать, что элемент — прямой потомок (селектор
>
) — неудобно, завтра ваш коллега добавит div-обёртку и все стили сломаются. В БЭМ, когда он ещё был АНБ, иногда писали селекторы вида .block-name .elem
, без селектора >
, но отказались (см. пункт [1]).Кстати, БЭМ не должен отображать структуру HTML :) Его задача — перевести DOM-дерево в BEM-дерево, наложив сверху CSS-классы как overlay, и структура при этом возникает новая.
1. Не до конца понял, можно пример смешивания из практики?
2. Я в ">" другой минус увидел, если, как в четвертом пункте, добавился новый слой, то надо будет как-то контролировать его добавление в js (при условии что используется $(".blockX > .item"), а не $(".blockX .item")).
А так, селектор есть селектор — пишется один раз.
3. Тут поспорю: при использовании ">" строка в css становиться больше, но, опять таки, она отображает структуру и гораздо нагляднее показывает на каком элементе срабатывает модификатор и как.
4. Теоретически такой «коллега» увидит по F5, но, да, без панно всех мест не отследить.
>и структура при этом возникает новая
Ох, не нравится мне когда структура одного и того же отличается, обычно это проблемы.
А есть причины менять структуру?
2. Я в ">" другой минус увидел, если, как в четвертом пункте, добавился новый слой, то надо будет как-то контролировать его добавление в js (при условии что используется $(".blockX > .item"), а не $(".blockX .item")).
А так, селектор есть селектор — пишется один раз.
3. Тут поспорю: при использовании ">" строка в css становиться больше, но, опять таки, она отображает структуру и гораздо нагляднее показывает на каком элементе срабатывает модификатор и как.
4. Теоретически такой «коллега» увидит по F5, но, да, без панно всех мест не отследить.
>и структура при этом возникает новая
Ох, не нравится мне когда структура одного и того же отличается, обычно это проблемы.
А есть причины менять структуру?
1.
Вложенный
2. В разметке бывает удобно переносить куски layout'а в другие места и знать, что JS не сломается. Чем меньше в JS зависимостей от структуры блока, тем лучше (это мой личный опыт, подтверждённый). Если б меня заставили перейти на схему с явно описанной структурой в стиле "
3. Не очень понял про спор насчёт специфичности. Дело вовсе не в длине строки, а в весе правил, меняется CSS Specificity, об этом есть абзац в статье. Плюс, в BEM всегда понятно, на каком блоке или элементе срабатывает модификатор, потому что модификатор всегда привязан к блоку или элементу, «абстрактных» модификаторов нет вообще.
Про структуру — вообще, структура должна быть описана шаблоном, это не уровень CSS, и тем более не JS. Жизнь не идеальна, но меньше связности == меньше регрессий при правках.
<div class="b-block">
<!-- ... какая-то разметка -->
<div class="b-widget">
<div class="b-block__container b-widget__item">
<!-- -->
</div>
</div>
</div>
Вложенный
div
(одна и та же нода) семантически является элементом container
блока block
и элементом item
блока widget
. Если не использовать BEM-именование, было бы <div class="container item"></div>
, и неясно, кто чей (а ещё оба элемента могли называться item
, тогда вообще весело)2. В разметке бывает удобно переносить куски layout'а в другие места и знать, что JS не сломается. Чем меньше в JS зависимостей от структуры блока, тем лучше (это мой личный опыт, подтверждённый). Если б меня заставили перейти на схему с явно описанной структурой в стиле "
A > B
", я б лично повесился в тот же день, but your mileage may vary :)3. Не очень понял про спор насчёт специфичности. Дело вовсе не в длине строки, а в весе правил, меняется CSS Specificity, об этом есть абзац в статье. Плюс, в BEM всегда понятно, на каком блоке или элементе срабатывает модификатор, потому что модификатор всегда привязан к блоку или элементу, «абстрактных» модификаторов нет вообще.
Про структуру — вообще, структура должна быть описана шаблоном, это не уровень CSS, и тем более не JS. Жизнь не идеальна, но меньше связности == меньше регрессий при правках.
Простите, всеравно не понимаю пример из 1.
Можете менее абстрактно объяснить, пожалуйста — почему один и тот же элемент может принадлежать разным блокам? Пример из жизни?
Можете менее абстрактно объяснить, пожалуйста — почему один и тот же элемент может принадлежать разным блокам? Пример из жизни?
Лучшая статья про BEM! Даже при всей моей любви к Яндексу, этот пост более информативен, чем «родной» экскурс по сей методологии на Хабре.
Спасибо :)
Оригинальная статья (на английском) была мною начата (как и написано в предисловии) как набор рекомендаций и пояснений про BEM для ребят из группы фронтенд-разработки, которой я руковожу тут, в компании Deltamethod в Берлине. Про основы BEM мало туториалов на английском, а какие есть — сделаны людьми, которые понимают BEM только как правила CSS-нейминга (а не как методологию). Уже потом я подумал, что можно сделать из этого полноценную статью :-)
Оригинальная статья (на английском) была мною начата (как и написано в предисловии) как набор рекомендаций и пояснений про BEM для ребят из группы фронтенд-разработки, которой я руковожу тут, в компании Deltamethod в Берлине. Про основы BEM мало туториалов на английском, а какие есть — сделаны людьми, которые понимают BEM только как правила CSS-нейминга (а не как методологию). Уже потом я подумал, что можно сделать из этого полноценную статью :-)
Это вам спасибо.
А оригинал я тоже читал (но на английском не так детально все было для меня) и даже рекомендовал его к переводу в одной из своих подборокэгоист.
А оригинал я тоже читал (но на английском не так детально все было для меня) и даже рекомендовал его к переводу в одной из своих подборок
Вопрос про английскую версию и детальность: дело в разнице языков, или в русском переводе формулировки другие? Я переводил более-менее один-в-один, но опыт перевода самого себя с английского на русский для меня нов; плюс, я не думал и не писал по-русски, когда делался оригинал статьи для Smashing. Интересно сравнить оба варианта со стороны :)
для моего случая и для начинающих — не помогают совсем, увы :( эти туториалы — и вообще весь bem.info — о том, как начать использовать «полный стек» БЭМ, а у меня была задача понять, как его можно НЕ использовать и при этом получить плюсы от внедрения методологии как таковой. это очень важная разница, критичная.
плюс, по ссылке нет материала для «совсем новичков», считается, что азы можно выучить самому, но для англоязычной аудитории это неверно.
мои ребята в Берлине просили материала на порядок более простого — про смысл всего подхода, про примеры выделения блоков в существующем коде, про подробности naming convention и зачем она нужна.
плюс, по ссылке нет материала для «совсем новичков», считается, что азы можно выучить самому, но для англоязычной аудитории это неверно.
мои ребята в Берлине просили материала на порядок более простого — про смысл всего подхода, про примеры выделения блоков в существующем коде, про подробности naming convention и зачем она нужна.
а родной — это какой?
А я тут немного натупил — не сразу заметил, что этот пост в корпоративном хабе присутствует, поэтому он тоже родной. Ну а так в целом, был же пост про БЭМ от Яндекса.
Элементы элементов не используются (например, имя класса .b-block__elem1__elem2 не соответствует БЭМ-подходу).
А почему кстати и как предлагается решать проблему, когда у блока несколько уровней вложенных элементов, которые по логике нет смысла выносить в блоки?
Посмотрел верстку папок на mail.yandex.ru:
b-folders
b-folders__folder
b-folders__folder__info
b-folders__folder__name
БЭМ — не канон, а методология. Я.Почта использует свой подход, у них есть элементы элементов, наверное, им зачем-то надо. В «классическом» БЭМ по умолчанию не описывается иерархия элементов, т.к. считается важным:
— иметь возможность свободно переставлять элементы внутри блока;
— оперировать только тремя сущностями (блок, элемент, модификатор) без усложнений;
— отделять семантически разные сущности друг от друга.
Если пойти на крайности, всю страницу можно описать как один блок с элементами неограниченной вложенности, но пользы от этого немного.
В реальной жизни идеалов не бывает. Есть у вас есть иерархия, которую надо отразить в БЭМ, можно вводить элементы элементов, можно делать
Я сам работал на проектах, где был вариант БЭМ с элементами элементов, и лично для себя пришёл к выводу, что «плоская» структура блоков — гибче.
— иметь возможность свободно переставлять элементы внутри блока;
— оперировать только тремя сущностями (блок, элемент, модификатор) без усложнений;
— отделять семантически разные сущности друг от друга.
Если пойти на крайности, всю страницу можно описать как один блок с элементами неограниченной вложенности, но пользы от этого немного.
В реальной жизни идеалов не бывает. Есть у вас есть иерархия, которую надо отразить в БЭМ, можно вводить элементы элементов, можно делать
b-folders__folder-name
и b-folders__folder-info
, можно вводить отдельный блок b-folder
и у него делать элементы b-folder__info
и b-folder__name
.Я сам работал на проектах, где был вариант БЭМ с элементами элементов, и лично для себя пришёл к выводу, что «плоская» структура блоков — гибче.
НЛО прилетело и опубликовало эту надпись здесь
очень хорошая идея про группу и роль, спасибо! беру на вооружение!
всё же блок и элемент как основные термины мне нравятся больше. во-первых, это устоявшиеся термины, это даже важнее локальных преимуществ переименования. во-вторых, группа подразумевает наличие нескольких вложенных сущностей (иначе кого мы группируем?), а в БЭМ блоки могут не иметь элементов вообще.
всё же блок и элемент как основные термины мне нравятся больше. во-первых, это устоявшиеся термины, это даже важнее локальных преимуществ переименования. во-вторых, группа подразумевает наличие нескольких вложенных сущностей (иначе кого мы группируем?), а в БЭМ блоки могут не иметь элементов вообще.
Кстати ещё про кнопки, допустим есть задача, сделать группу кнопок, которые ведут себя как radio-button. Обычные кнопки и группа должны выглядеть примерно одинаково и по логике такие кнопки должны быть одним и тем же блоком, а вот группа, это просто какой-то модификатор у родительского контейнера, который корректирует дочерние элементы, собственно в этом и вопрос, как это должно быть описано в идеальном или не очень BEM?
У нас радио-группа реализована отдельным блоком:
ru.bem.info/libs/bem-components/v2/desktop/radio-group/
github.com/bem/bem-components/tree/v2/common.blocks/radio-group
github.com/bem/bem-components/tree/v2/design/common.blocks/radio-group/_theme
ru.bem.info/libs/bem-components/v2/desktop/radio-group/
github.com/bem/bem-components/tree/v2/common.blocks/radio-group
github.com/bem/bem-components/tree/v2/design/common.blocks/radio-group/_theme
Но это же copy-paste и ещё при изменении стиля кнопок, нужно будет менять уже не один блок, а несколько, притом ещё и нужно будет ещё найти и понять, что они тоже должны быть «как кнопки». Или у вас для этого есть какое-то элегантное решение?
Вот так декларируется кнопка:
А вот так радиогруппа на основе кнопок:
Шаблоны на radio-group написаны таким образом, чтобы каждый элемент options превратился в полноценную кнопку, смиксованную с элементом radio-group.
Поэтому никакого копипаста нет, зато API каждого блока отвечает именно тем задачам, которые перед ним стоят.
{
block : 'button',
text : 'Тема не указана'
}
А вот так радиогруппа на основе кнопок:
{
block : 'radio-group',
mods : { type : 'button' },
name : 'Small',
options : [
{ val : 1, text : 'first' },
{ val : 2, text : 'second' }
]
}
Шаблоны на radio-group написаны таким образом, чтобы каждый элемент options превратился в полноценную кнопку, смиксованную с элементом radio-group.
Поэтому никакого копипаста нет, зато API каждого блока отвечает именно тем задачам, которые перед ним стоят.
Ага, понял, посмотрел верстку, мы просто недопоняли друг друга, блок control-group у вас выступает как модификатор для дочерних button, а css находится в описании самой кнопки. Это нормально?
control-group отвечает только за визуальное объединение других контролов (например, убирает скругление углов у двух стоящих рядом кнопок или у инпута и кнопки).
Поэтому реализация того, как именно меняется внешний вид конкретного блока с конкретной темой логично хранить внутри реализации его темы, а микс с control-group выступает удобным консистентным API для этой задачи.
Поэтому реализация того, как именно меняется внешний вид конкретного блока с конкретной темой логично хранить внутри реализации его темы, а микс с control-group выступает удобным консистентным API для этой задачи.
В мире, где не используется полный BEM-стек (про который и написана статья), эти проблемы правильнее решать либо миксинами на уровне CSS-препроцессора, обобщая в них всё визуальное, либо выносом общих свойств и поведения в основной блок и созданием специальных модификаторов под отдельные случаи (когда обычная кнопка должа вдруг начать вести себя как радиокнопка).
История с тем, как вынести вовне общий код у компонент, которые похожи друг на друга, но не сильно — стара, как мир. В определённый момент (я в этом твёрдо уверен) надо рвать «наследственную связь» и копипастить, потому что поддержание зависимостей со множественным переопределением себя не оправдывает с практической точки зрения — будут сплошные баги и регрессии, которые съедят всё время, которое сэкономит shared code base.
История с тем, как вынести вовне общий код у компонент, которые похожи друг на друга, но не сильно — стара, как мир. В определённый момент (я в этом твёрдо уверен) надо рвать «наследственную связь» и копипастить, потому что поддержание зависимостей со множественным переопределением себя не оправдывает с практической точки зрения — будут сплошные баги и регрессии, которые съедят всё время, которое сэкономит shared code base.
Есть, конечно. Базовые блоки. Копипаста нет, просто блок, который группа, использует в себе как зависимость другой блок. И в случае смены стиля кнопки, к примеру, стиль группы измениться тоже.
Отличная статья, спасибо! Давно хотел разобраться с БЭМ и как начать его использовать в своих проектах, желательно без полного стека инструментов — не хватало как раз такого легкоусвояемого материала.
Я использую Angular в своем проекте, что можете сказать об удобстве использования БЭМ с этим фреймворком, есть ли какие-то ограничения? Что-нибудь почитать на эту тему или примеры проектов очень бы помогли.
Я использую Angular в своем проекте, что можете сказать об удобстве использования БЭМ с этим фреймворком, есть ли какие-то ограничения? Что-нибудь почитать на эту тему или примеры проектов очень бы помогли.
Спасибо!
Я не использую Angular, к сожалению.
На минском БЭМ-митапе был доклад про это, вот страничка мероприятия, и в тексте есть ссылки на докладчика и описание темы, наверняка можно связаться или раздобыть дополнительные сведения:
tech.yandex.ru/events/bemup/18-april-2014/
Я не использую Angular, к сожалению.
На минском БЭМ-митапе был доклад про это, вот страничка мероприятия, и в тексте есть ссылки на докладчика и описание темы, наверняка можно связаться или раздобыть дополнительные сведения:
tech.yandex.ru/events/bemup/18-april-2014/
Можете посмотреть мой доклад tech.yandex.ru/events/bemup/17-may-2014/talks/1928/, мы используем Angular. И еще надо взглянуть вот сюда github.com/verybigman/bem-ng.
1. может быть глупый вопрос, а у вас верстальщик пишет шаблоны bemhtml?
2. как мне писать директивы для ангуляра и при этом использовать шаблоны bemhtml?
2. как мне писать директивы для ангуляра и при этом использовать шаблоны bemhtml?
1. Да, bemhtml.
2. Есть нюансы в сборке. Мы отделили Angular приложение, как в MEAN стеке, там и пишем директивы. Вьюхи собираются из другой директории и складываются с помощью Gulp. i-bem.js не включается в итоговую сборку скриптов, это искусственное ограничение, чтобы избежать конфликтов.
Ответил на вопрос? Посмотрите еще вот сюда github.com/verybigman/generator-bem
2. Есть нюансы в сборке. Мы отделили Angular приложение, как в MEAN стеке, там и пишем директивы. Вьюхи собираются из другой директории и складываются с помощью Gulp. i-bem.js не включается в итоговую сборку скриптов, это искусственное ограничение, чтобы избежать конфликтов.
Ответил на вопрос? Посмотрите еще вот сюда github.com/verybigman/generator-bem
Сейчас как раз интересуюсь БЭМ и АНБ. Полный стек не интересует — интерес вызывает наименования классов и файловая структура.
Вроде кажется что все просто и понятно, но потом решаешься попробывать на большом проекте, и вот тогда начинаются вопросы.
1) По метолологии все блоки, лежат в папке blocks. Но что делать, если блоков становится слишком много? Я конечно понимаю, что можно их ка кто разбить на модули по типу
А как все таки с точки зрения БЭМ решать эту проблему?
2) Такие инструменты как SASS дают хорошую возможность. использовать, например, переменные, различного вида хелперы, миксины, наследование. Но, если мы с блоке начинаем юзать что-то из этого, но он же перестает быть независимым и становиться зависимым от контекста. То есть, либо мы нарушаем АНБ, либо пишем кучу повторяющегося кода.
Как БЭМ смотрит на эту проблему?
Вроде кажется что все просто и понятно, но потом решаешься попробывать на большом проекте, и вот тогда начинаются вопросы.
1) По метолологии все блоки, лежат в папке blocks. Но что делать, если блоков становится слишком много? Я конечно понимаю, что можно их ка кто разбить на модули по типу
blocks/
..module1/
....block1/
....block2/
..module2/
....block1/
....block2/
А как все таки с точки зрения БЭМ решать эту проблему?
2) Такие инструменты как SASS дают хорошую возможность. использовать, например, переменные, различного вида хелперы, миксины, наследование. Но, если мы с блоке начинаем юзать что-то из этого, но он же перестает быть независимым и становиться зависимым от контекста. То есть, либо мы нарушаем АНБ, либо пишем кучу повторяющегося кода.
Как БЭМ смотрит на эту проблему?
1. Можно группировать блоки по смыслу. Например, мы используем группировку по платформам: common.blocks, desktop.blocks, touch.blocks и т.д.
2. Блоки могут иметь зависимости, только эти зависимости должны быть явные. Чтобы при необходимости повторно использовать блок, его перенос на другой проект автоматически доставлял все зависимости. См. пример.
2. Блоки могут иметь зависимости, только эти зависимости должны быть явные. Чтобы при необходимости повторно использовать блок, его перенос на другой проект автоматически доставлял все зависимости. См. пример.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Масштабирование наоборот: БЭМ-методология Яндекса на небольших проектах