Мы подготовили описание БЭМ-метода на русском и английском языках:
Документ описывает общие принципы методологии и возможные варианты технической реализации.
Разработка документа ведётся в репозитории на GitHub: https://github.com/bem/bem-method/tree/gh-pages. Можно участвовать через правку в своих форках.
Спасибо: https://github.com/bem/bem-method/issues/57
Кажется в картинке http://bem.github.com/bem -method/images/levels.ru. png ошибка - в первой нижней ячейке должно быть "block 1", а не 3
Есть вопросы по БЭМ-методологии:
1. "Можно ли в элементе размещать другие элементы?"
Судя по описанию, что нельзя. Но если глянуть на html-код яндекс почты, то можно увидеть названия типа "b-mail-dropdown__item__content" .
2. Как это понимать?
3. И на самом деле, как (по БЭМ методологии) организовать структуру банального блока меню (ul > li > a) ? Получается, что
- это блок,- - это элемент, а - это что? Ведь по логике получается, что тут уже
- - это блок, а - это элемент. А что делать, если еще могут понадобится различные wrapper'ы.
2. Понимать так, что это элемент content, который имеет смысл только внутри элемента item, поэтому у него "составное" имя - __item__content
3. Можно по-разному.
Вот так:
Вот так:
Вот так:
Это очень зависит от дизайна, и от того, какой смысл вы хотите вложить в свою разметку. Например, на сервисах Яндекса используется весьма лаконичный дизайн и ссылки практически везде выглядят просто и одинаково. Поэтому мы как правило будем верстать ссылку в выпадающем меню как обычный b-link.
А на каких-нибудь других сайтах ссылки в контенте могут выглядеть одним образом (обычные синие), а ссылки в основной навигации совсем по-другому, и им вообще не нужны стили от базового блока b-link.
b-menu -> b-menu__item -> b-link
b-menu -> b-menu__item -> b-menu__link
b-menu -> b-menu__item -> b-menu__item__link
на некоторых яндексовых проектах есть и b-menu__item__link, но это ничего не значит
1. По вёрстке — можно, а в файловой структуре они должны быть плоским списком.
Вообще делать можно как угодно, и вкладывать элемент в элемент (как сделали в Почте), но наша рекомендация такая, как в документе.
3. a - это блок b-link, вложенный в элемент li. На самом деле зависит от реализации, может быть и элементом списка.
Хотя я и не согласен с полным отсутствием поддержки, но да, почти всегда лучше разделять всё на блоки, чем плодить подэлементы.
Может этот вопрос в клубе раскрыть, с примерами, почему в итоге так решили, какие были проблемы и т.д.? Это бы лучше воспринималось. Мне (и, наверняка, многим другим читателям) интересно читать не только «что» и «как» было сделано, но и «почему». Было бы интересно почитать про подобные моменты в методологии.
пока коротко могу сказать, что это увеличивает связность и контекстную зависимость разных частей, а это ударяет как по простоте восприятия конструкций (простые конструкции сложнее проектировать но проще воспринимать), так и по скорости работы в разных местах (от шаблонов до клиентского js)
Vitaly Friedman
…и опубликуйте статью на Smashing Magazine. Обычного перевода мало.
Спасибо. Обязательно напишем попозже, когда будет больше информации на английском, мы над этим работаем.
"b-menu -> b-menu__item -> b-menu__link"
супер!
я почему-то раньше считал, что элемент должен быть непосредственным чилдом блока, а оказывается, что еще он может находиться в другом элементе, но считаться элементом блока.
Теперь все стало на свои места. Спасибо!
А то раньше иногда приходилось "извращаться" в css писать "b-menu__item>a", но, как неоднократно показала практика (и как в методологии сказано), привязка к тэгам - это зло.
по поводу модификаторов.
както нелогично получается при "b-bloc__element b-bloc__element_xxxx" называть "b-bloc__element_xxxx" модикатором . ведь по сути "b-bloc__element_xxxx" такойже класс элемента как и ""b-bloc__element" . потому как то состояние которое он в себе несет изначально заложенно в элемент.
а вот ситуацию "b-block b-wrap-block__eeee" где класс "b-wrap-block__eeee" делает какрастаки модификацию никак не отмечена.
если развить тему "истенных модификаторов" то можно отдать префиксам роль выделять классы "истенных модификаторов" среди других. тапа так "b-block m-wrap-block__eeee" или "b-block i-img_bg-star"
Изначально были id-шники, и для блоков (например, формы поиска) мы писали как-то так:
Потом мы поняли, что блоки могут повторяться на странице и нам хочется как можно меньше делать изменений при этом. Так например форма поиска однажды появлялась внизу выдачи, чтобы было удобнее перезадавать запрос по прочтении результатов. И мы приняли решение, всегда использовать классы, чтобы лишний раз не менять css, если блок будет повторяться:
Потом настала необходимость немного изменить нижнюю форму поиска, сделать её не такой большой. Мы придумали добавлять ещё один класс-модификатор (тогда это было просто слово, а не ключ/значение как сейчас, но об этом ниже):
Отдельно стоит сказать, что из-за IE мы тогда не смогли использовать совмещение классов вот так:
И это позже нам даже помогло, когда мы стали смешивать разные БЭМ-сущности на одной HTML-ноде.
Время шло, блоков становилось больше и они становились сложнее, перестало хватать слов одиночных чтобы понятно именовать сущности. Мы попробовали несколько вариантов:
Примерно тогда же, мы начали использовать что-то типа венгерской нотации, указывая разные префиксы для разных типов блоков. Были разные b-, l-, w-, g- и ещё какие-то, но в итоге можно считать выжившими b- для визуальных самостоятельных блоков и i- для вспомогательных, не использующихся в явном виде самостоятельно. Стоит сказать, что сейчас эти префиксы уже скорее дань истории и та часть, которую мы не меняем по причине сильной распространённости внутри, а вовсе не что-то обязательное (без префиксов легко можно жить!).
Прошло ещё больше времени и модификаторов стало становиться ещё больше. Появились такие модификаторы как: цвет, размер, тип и прочие. Некоторые модификаторы стали пересекаться по значениям. Появились проблемы в работе с модификаторами из клиентского JS, т.к. класс не содержал имени модификатора, а следовательно небыло полной информации. И мы пришли к тому, что модификатор это именно ключ (название модификации) и значение. И это должно быть в CSS-классе:
К слову, это было одно из самых болезненных изменений, которое очень долго внедряли по сервисам.
Практически в тоже время мы поняли, что очень удобно для многих случаев, иметь возможность смешивать несколько БЭМ-объектов на одной HTML-ноде.
К этому времени это получилось абсолютно логично и без всяких проблем, благодаря тому, что в классе для модификатора содержалось имя блока (привет IE
Вот такая история
Я расскажу, примерно и кратко, откуда появились модификаторы.
Изначально были id-шники, и для блоков (например, формы поиска) мы писали как-то так:
HTML:
CSS:
#search { ... }
Потом мы поняли, что блоки могут повторяться на странице и нам хочется как можно меньше делать изменений при этом. Так например форма поиска однажды появлялась внизу выдачи, чтобы было удобнее перезадавать запрос по прочтении результатов. И мы приняли решение, всегда использовать классы, чтобы лишний раз не менять css, если блок будет повторяться:
HTML:
CSS:
.search { ... }
Потом настала необходимость немного изменить нижнюю форму поиска, сделать её не такой большой. Мы придумали добавлять ещё один класс-модификатор (тогда это было просто слово, а не ключ/значение как сейчас, но об этом ниже):
HTML:
CSS:
.search { ... основные стили ... }
.search-small { ... стили для уменьшения размера ... }
Отдельно стоит сказать, что из-за IE мы тогда не смогли использовать совмещение классов вот так:
HTML:
CSS:
.search.small { ... стили для уменьшения размера ... }
И это позже нам даже помогло, когда мы стали смешивать разные БЭМ-сущности на одной HTML-ноде.
Время шло, блоков становилось больше и они становились сложнее, перестало хватать слов одиночных чтобы понятно именовать сущности. Мы попробовали несколько вариантов:
searchform searchform-small — один токен пишется одним словом, разделитель токенов дефис (не очень красивые слова получались)
SearchForm SearchForm-Small — CamelCase для слов в токене, разделитель токенов дефис (мы привыкли не использовать верхний регистр и этот вариант тоже не прижился)
search-form search-form_small — один токен пишется с дефисами между словами, разделитель токенов нижнее подчёркивание (прижившийся вариант, чем-то напоминает xsl)
Примерно тогда же, мы начали использовать что-то типа венгерской нотации, указывая разные префиксы для разных типов блоков. Были разные b-, l-, w-, g- и ещё какие-то, но в итоге можно считать выжившими b- для визуальных самостоятельных блоков и i- для вспомогательных, не использующихся в явном виде самостоятельно. Стоит сказать, что сейчас эти префиксы уже скорее дань истории и та часть, которую мы не меняем по причине сильной распространённости внутри, а вовсе не что-то обязательное (без префиксов легко можно жить!).
Прошло ещё больше времени и модификаторов стало становиться ещё больше. Появились такие модификаторы как: цвет, размер, тип и прочие. Некоторые модификаторы стали пересекаться по значениям. Появились проблемы в работе с модификаторами из клиентского JS, т.к. класс не содержал имени модификатора, а следовательно небыло полной информации. И мы пришли к тому, что модификатор это именно ключ (название модификации) и значение. И это должно быть в CSS-классе:
HTML:
CSS:
.b-search-form { ... основные стили ... }
.b-search-form_size_small { ... стили для уменьшения размера ... }
К слову, это было одно из самых болезненных изменений, которое очень долго внедряли по сервисам.
Практически в тоже время мы поняли, что очень удобно для многих случаев, иметь возможность смешивать несколько БЭМ-объектов на одной HTML-ноде.
HTML:
К этому времени это получилось абсолютно логично и без всяких проблем, благодаря тому, что в классе для модификатора содержалось имя блока (привет IE
Вот такая история
Предпоследний абзац непонятен. Можно пояснить о чём в нём говорится? О каких проблемах речь? Как они решены? Приведённые два класса в примере ни о чём не говорят.
если бы модификаторы по историческим причинам не содержали в себе имя модифицируемого блока, то миксы нескольких блоков на одной ноде были бы очень спорным и шатким решением
оу, неожидал так много
но я не об этом ) это было предложенение по улечшению. Не называть ключи(флаги, биты, состояния, ... или еше как там их можно назвать) модификатором. потому как это зарание зашитые состояния элемента в контексте блока.
Модификатором назвать классы которые не относятся к данному блоку, и отличать их от классов(элемента в блоке) префиксом.
Префикс не является частью имени блока. Префикс это подсветка кода.
Префиксы
Да, понятно, что ничто не мешает, в принципе, писать просто search-form вместо b-search-form.
Семантика
У вас не было ярых сторонников семантичности, которые протестовали против введения классов-модификаторов? Я уже слышу их доводы: "это сейчас нижняя форма маленькая и желтая, а верхняя большая и красная! Что если завтра верхняя станет маленькой и зеленой?! Мы не сможем просто поменять css, нам придется изменять классы, проходя по всем страницам, где эта форма использовалась!"
Шаблоны
Еще не совсем понятен один момент. Например, на сайте используются два типа страниц. В одном случае страница состоит из меню и контента в одну колонку, в другом контент разбит на две колонки. В большинстве популярных шаблонизаторов мы бы присвоили этим страницам примерно такие шаблоны:
//первый шаблон
<% вставить контент %> //сюда вставится меню
<% вставить контент %> //сюда вставится все остальное
//второй шаблон
<% вставить контент %> //сюда вставится меню
<% вставить контент %> //сюда вставится все остальное
<% вставить контент %> //сюда вставится все остальное
В случае использования БЭМ-шаблонизатора, как я понимаю, column - это блок. Но если нам нужно верстать кучу страниц по второму из представленных выше шаблонов, то, наверное, мы захотим сохранить "пресет" из страницы с двумя блоками column и блоком menu. У вас, наверное, это реализовано на уровне инструментов? Или я что-то не понимаю?
В шаблонизаторе BEMHTML есть возможность порождать новые блоки внутри шаблонов. Получается что-то вроде инклудов, только поумнее.
Попробую написать пример в понедельник.
"миксированием" так можно назвать процесс. ито лучше подобрать какоенибуть русское слово чтоб документация была более понятной. к примеру "Смешивание классов" )
я лишь высказал свое мнение.
Интересно увидеть пример из реальной жизни где смешивание блоков на одной ноде оказалось полезным решением.
самый простой пример
https://skitch.com/tyv/8pnc2/-bem-
Но ведь если классы модификаторов нигде не написаны в css в виде без префикса имени блока, то проблем не будет, нет?
Ваш пример:
class="b-leave-comment b-leave-comment_type_share g-hidden"
превращаем в class="b-leave-comment _type_share g-hidden"
а в css:
.b-leave-comment {стили базового блока}
.b-leave-comment._type_share {стили модификатора}
к сожалению, теряется выразительность и однозначность
А мне со-стороны кажется наоборот - код стал яснее и красивей. Особенно заметно на блоках вида:
Я понимаю так: хоть это и микс - это ведь всё равно у нас один конечный элемент. Один элемент, вобравший в себя части нескольких. В данном примере некая "ссылка,с иконкой,с логотипом, где-то внизу". И т.к. это один элемент, то и состояние у него тоже одно на всех, точнее эти состояния относятся к нему как элементу вцелом, а не к каким-то его отдельным частям.
В данном случае: "состояние сфокурисовано:да, активно: да, размер: xxl"
Нужные визуальные метаморфозы задаются стрго через multiple classes, например:
В JS тоже обращение по multiple classes.
Понятно что Яндекс уже не может (из-за огромной базы кода), да и не нуждается (в силу автоматической генерации кода), в такой нотации. Но если у нас только начинается библиотка блоков "по-БЭМ", отчего-же нет?
Посмотрел.
Вижу один главный довод - в случае наличия библиотеки блоков и прочесса сборки, сокращённые модификаторы через multiple classes могут вызывать конфликты. Эти конфликты можно разруливать через стили вида: .element1.element2.mod - (т.е. стиль который применяется только тогда когда два элемента с одним модификатором появляются на одной ноде)... но в условиях большой компании и библиотеки блоков - это нецелесообразно.
А вот когда сборки нет и нет огромной библиотеки и огромных миксов, то не вижу повода не юзать сокращённую форму.
Ну т.е. - для Яндекса это неверно, но ведь у BEM - нет единственно верного варианта.