В комментах html написаны тезисы доклада и комментарии к слайдам требующим пояснений.
Презентация: delka.github.io/talks/2015/frontendweekend-bem/
Есть DOM-дерево, а есть БЭМ-дерево.
<input class="big_red_button"><input class="big_red_buttonorder-button"><input class="order-button discount-checkout__submit">
device-template-generic-indicator-control-slider-bar-d :)Что в этом коде относится к классу user ?
<div class="media user premium"><img class="img photo avatar" src="" /><p class="body bio">...</p></div>
Если мы перепишем этот код на BEM CSS, то все будет понятно просто из имён классов!
<div class="media user--premium"><img class="media__img user__photo avatar" src="" /><p class="media__body user__bio">...</p></div>
* CSS подмножество БЭМ
bemjson, bemhtml, bem-tools, enb, вот это вот всё…
Когда он будет вам нужен — вы это сами поймёте.
Это будет момент, когда вам надоест писать html руками и вы захотите его генерировать.
НБ или просто блок, это самодостаточный элемент страницы, который при перемещении в другое место на странице или на другую страницу не теряет своей самодостаточности.
Логически и функционально независимый компонент страницы, аналог компонента в Web Components. Блок инкапсулирует в себе поведение (JavaScript), шаблоны, стили (CSS) и другие технологии реализации. Независимость блоков обеспечивает возможность их повторного использования, а также удобство в разработке и поддержке проекта.
- для описания элемента используется class, но не id
- каждый блок имеет префикс
- в таблице стилей нет классов вне блоков
Просто писать стили тупо на каждый блок.
БЭМ хорош тем, что позволяет не забивать голову ерундой с каскадом, а сосредоточиться на семантике и логике кода.
А с препроцессорами БЭМ позволяет писать еще и очень чистый и логичный код.
Просто навести на блок в инспекторе кода.
У него не должно быть каскада.
На самом деле каскад допускается, но его следует избегать.
Элемент – это часть блока, отвечающая за отдельную функцию.
Он может находиться только в составе блока и не имеет смысла в отрыве от него.
Можете себе представить что это как папки в файловой системе, способ организации кода, чтобы было понятно, что к чему относится.
<ul><li><a><span></span></a></li></ul>
.ul {}.ul > li {}.ul > li > a {}.ul > li > a > span {}
<ul class="menu"><li class="menu__item"><a class="menu__link"><span class="menu__text"></span></a></li></ul>
.menu {}.menu__item {}.menu__link {}.menu__text {}
БЭМ-дерево не зависит ни от чего, даже от размещения в документе.
БЭМ-дерево не привязано к визуальному представлению блоков, оно отображает только логику, это и есть новый уровень семантики!
Да и не только за рубежом, чё уж греха таить…
.form-buy-results__to-city__slider__tab__column_buy
Так делать нельзя
<div class="block"><div class="block__elem1"><div class="block__elem2"></div></div><div class="block__elem3"></div></div>
.block {}.block__elem1 {}.block__elem2 {}.block__elem3 {}
<div class="block"><div class="block__elem1"><div class="block__elem1__elem2"></div></div></div>
<div class="block1"><div class="block1__elem1 block2"><div class="block2__elem1"></div></div></div>
.block1 {}.block1__elem1 {}.block2 {}.block2__elem1 {}
<div class="block1"><div class="block1__elem1"><div class="block1__elem2"></div></div></div>
.block1 {}.block1__elem1 {}.block1__elem2 {}
Чтоб «схитрить» и «как-будто не вложить», написать не .block__el1__el2 а .blockel1__el2 или .block__el1el2. Так нельзя.
.block {}.blockel1 {}.blockel1__el2 {}
Будут проблемы при переносе
Попытались перенести «странный элемент» в другое место - получили элемент что завис «в воздухе» без блока-родителя
<div class='someblock'><div class='blockel1__el2'></div></div>
Так можно делать только если .blockelem сохранит логический смысл при переносе в другой блок.
Обратите внимание - вы не можете вкладывать элементы в элементы в CSS, но можете и должны вкладывать элементы в элементы в HTML! DOM-дерево и БЭМ-дерево могут быть разными.
БЭМ-дерево на то и дерево, что поддерживает вложенность, поэтому в БЭМ-дереве, разумеется, разрешается вкладывать элементы в элементы, блоки в блоки, блоки в элементы.
NB: это и есть суть БЭМ, то, что многие не понимают.
Погружаясь вглубь DOM, нужно стараться создавать новые и новые блоки, а не строить связи родитель__элемент__элемент.
<div class="block1"><div class="block1__elem1 block2"><div class="block2__elem1"></div></div></div>
<div class="b-blog"><div class="b-blog_item b-post"></div></div>
В этой DOM-ноде смешиваются стили от 2-х разных блоков:
.b-blog__item) — стили раскладки, позиционирование,.b-post) — внешний вид самого блока.Эти стили объединяются в одном html-элементе и создают таким образом связи между блоками.
.b-blog {// блок@at-root .b-post {// ещё один блок}}
.b-blog {/* стили блока */}.b-post {/* ещё один блок */}
Позиционирование — на элементе родителя и блоке родителя, стили блока — на новом блоке.
<div class="b-blog"><div class="b-blog_item b-post"></div></div>
Позиционирование — на классах сетки, стили блоков — на самих блоках.
<div class="b-blog b-grid"><div class="b-grid__col b-post"></div></div>
Позиционирование — на классах сетки, стили блоков — на самих блоках.
<div class="b-blog"><div class="b-grid"><div class="b-grid__col"><div class="b-post"></div></div></div></div>
l-, h-)
Позиционирование — на блоках-врапперах.
Связей между блоками (блок—элемент) больше нет!
Яндекс НЕ рекомендует! Но этот вариант часто встречается в жизни.
<div class="l-blog"><div class="b-blog"><div class="l-post"><div class="b-post"></div></div></div></div>
Это не нужно для БЭМ, просто я люблю микроформаты, Гугл любит микрофрматы и Яндекс тоже любит микроформаты :) Классно что мы можем добавлять любые имена классов куда-угодно, все стили у нас — только на БЭМ-классах.
<div class="block1"><div class="block1__elem1 block2"><div class="block2__elem1"></div></div><div class="block1__elem2"></div></div>
.block1 {}.block1__elem1 {}.block1__elem2 {}.block2 {}.block2__elem1 {}
<div class="block-name__elem_key_value">
А для элементов — делай каскад от модификатора.
Если речь идет о простых правках, типа «активный пункт меню», то да, можно:
<a class="menu__link menu__link_state_active">
Кстати в таких простых случаях, можно писать модификаторы просто одним словом:
<a class="menu__link menu__link_active">
В случае ручной верстки, это сигнал об ошибках в вашей логике разбиения на блоки. Признак неудачного проектирования родительского блока. Если вам нужен модификатор на элемент — вам скорее нужно сделать из этого элемента новый блок.
Например, слайдеры очень часто верстают дикой вложенностью.
В html как-будто всё ok:
<div class="block"><div class="block__el">
А на деле сели в машину и сгорели:
/* CSS */.block .block__el {}
<ul class="menu checkoutForm big myfuckingclass-bold">
Да потому что из-за этого потом тяжелей вносить правки и сложно переместить блок в другое место.
от Александра Корецкого @n2j7 из Prom.ua
<ul class="b-list h-mt-20 h-mb-50 h-pointer h-left h-colorred">--float_left).list__item1,.list__item2,…)Как назначаются стили для типографики? Не будешь же назначать каждому тегу какой-то класс?
.b-text блоку родителюИ использовать каскад.
.b-text h2 {}.b-text p {}.b-text img {}.b-text ul li {}
Конечно при большом желании можно настроить визивиг, тот же TinyMCE, чтоб он добавлял нужные имена классов в тегах из визивига.
.b-list {/* стили блока *///…&__item {/* стили элемента */}&__link {/* элемент #2… */}}
.b-list {/* стили блока */}.b-list__item {/* стили элемента */}.b-list__link {/* элемент #2… */}
.b-list {/* стили блока */&--style_numered {/* стили модифицированного блока */}}
.b-list {/* стили блока */}.b-list--style_numered {/* стили модифицированного блока */}
.b-list {/* стили блока */&__item {/* стили элемента */&--active {/* стили модифицированного элемента */}}}
.b-list {/* стили блока */}.b-list__item {/* стили элемента */}.b-list__item--active {/* стили модифицированного элемента */}
.b-list {$rootParent: &;&__item {/* обычный элемент */}&--style_numered {/* модифицированный блок */#{$rootParent}__item {/* элемент модифицированного блока */}}}
* Это разрешённая практика в БЭМ, но изменение стилей не должно быть монструозным.
.b-list {$rootParent: &;&__item {/* обычный элемент */#{$rootParent}--style_numered & {/* элемент модифицированного блока */}}}
* Это разрешённая практика в БЭМ, но изменение стилей не должно быть монструозным.
.b-list {/* стили блока */}.b-list__item {/* стили элемента */}.b-list--style_numered b-list__item {/* стили элемента модифицированного блока */}
.b-list {$rootParent: &;&__item {/* элемент */}&__link {/* элемент */#{$rootParent}__item--active & {// наглый модификатор элемента}}}
* Так делать неправильно. Модификация элемента элементом — нарушение правил! Но бывает нет выхода.
.b-list {/* блок */}.b-list__item {/* элемент */}.b-list__link {/* элемент */}.b-list__item--active .b-list__link {/* наглый модификатор элемента */}
b-,l-,g-,i-,h-,m-,c- и js-,
|
qa-,o-,c-(другой :),u-,t-,s-,is-,has-…
|
Были в раннем БЭМ. Сейчас пропагандируются Гарри Робертсом и используются многими не-Яндекс разработчиками. Используются для создания своего пространства имен и логического разделения блоков.
Продвинутое использование префиксов и суффиксов от Гарри Робертса. Попытка описать взаимосвязь между независимыми блоками с точки зрения SMACSS и OOCSS.
Многим нравится зарубежный формат модификаторов, через „--“, он читабельней.
<a class="block-name__element-name--state_active">
А через camelCase – ещё читабельней!
<a class="blockName__elementName--state_active">
Некоторые идут ещё дальше и заменяют „__“ на „-“. camelCase единственный гарантирует что вы поймете где блок, а где элемент.
<a class="blockName-elementName--state_active">
Правильно писать так:
.block-name__elem_key_value
Или так:
.blockName__elem--key_value
<div class="block-name block-name_key1_val1 block-name_key2_val2 block-name_key3_val3">
Нет дуракоустойчивости, модификатор могут перенести без блока:
<div class="block-name_key1_val1 some-another-block">
Хочется так:
<div class="block-name -key1_val1 -key2_val2 -key3_val3">
За рубежом их назвали „Individual modifiers: a shorter syntax“. У нас перевели как «Обособленные модификаторы: сокращенный синтаксис». Яндекс в официальной документации называет их «Стиль No-namespace».
<div class="blockName__elem -key_value">.blockName {&__elem {&.-key_value {}}}
<div class="block-name block-name_key1_value1 block-name_key2_value2 block-name_key3_value3">
<!-- VS --><div class="block-nameblock-name_key1_value1block-name_key2_value2block-name_key3_value3">
А ещё можно юзать Jade, а в Яндексе вообще не пишут html-код руками, у них BEMJSON.
$('.js-fancybox').fancybox();
Это миксование css-блока и js-блока на одной dom-ноде.
Канонический БЭМ считает, что они не нужны, т.к. js-функционал нет смысла отделять от блока.
Гарри Робертс и не-Яндекс разработчики их активно используют и пропагандируют: т.к. разделение позволяет легко копировать css-блок без связанного с ним JS.
Известный пример использования методологии БЭМ сторонним разработчиком - Артёмом Сапегиным
Диалект БЭМ, с более строгими правилами для максимальной надежности верстки, придуманный Вадимом Макишвили для Яндекс.Карт.
Библиотека блоков от Google, css-реализации их Material Design придуманного для Android.
БЭМ дает лишь базовый набор правил, конкретную реализацию и синтаксис вы выбираете сами.
Кое-что мы с вами обсудили/упомянули:
js- блоки)(i-)(m-)(h-)b- и что такое независимый блок
Презентация: delka.github.io/talks/2015/frontendweekend-bem/
Видео доклада: youtube.com/watch?v=kBgHdSOj33A
Презентация, которую вы смотрите, содержит больше слайдов и примеров, чем оригинальное видео.