В комментах 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 руками и вы захотите его генерировать.
Просто писать стили тупо на каждый блок.
БЭМ хорош тем, что позволяет не забивать голову ерундой с каскадом, а сосредоточиться на семантике и логике кода.
А с препроцессорами БЭМ позволяет писать еще и очень чистый и логичный код.
Просто навести на блок в инспекторе кода.
У него не должно быть каскада.
На самом деле каскад допускается, но его следует избегать.
Можете себе представить что это как папки в файловой системе, способ организации кода, чтобы было понятно, что к чему относится.
<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-name
block-name_key1_value1
block-name_key2_value2
block-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
Презентация, которую вы смотрите, содержит больше слайдов и примеров, чем оригинальное видео.