В комментах 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>
<LI>
<A>
<SPAN></SPAN>
</A>
</LI>
</UL>
<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 {}
<UL class="menu">
<LI class="menu__item">
<A class="menu__link">
<SPAN class="menu__text"></SPAN>
</A>
</LI>
</UL>
БЭМ-дерево не зависит ни от чего, даже от размещения в документе.
БЭМ-дерево не привязано к визуальному представлению блоков, оно отображает только логику, это и есть новый уровень семантики!
Да и не только зарубежом, чё уж греха таить…
.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 {
/* стили блока */
}
.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 {
/* наглый модификатор элемента */
}
Верстаем надпись «Привет», input и кнопку.
({
block : 'page',
title : 'hello',
head : [
{ elem : 'css', url : 'hello.min.css' }
],
scripts : [{ elem : 'js', url : 'hello.min.js' }],
mods : { theme : 'islands' },
content : [
{
block : 'hello',
content : [
{
block : 'hello',
content : [{
elem : 'greeting',
content : 'Привет, %пользователь%!'
},{
block : 'input',
mods : {theme : 'islands', size : 'm'},
name : 'name',
placeholder : 'Имя пользователя'
},
{
block : 'button',
mods : {theme : 'islands', size : 'm',
type : 'submit'},
text : 'Нажать'
}
]
}
]
})
Тепер надо написать BEMHTML.
block('hello')(
js()(true),
tag()('form')
);
Известный пример использования методологии БЭМ сторонним разработчиком - Артёмом Сапегиным.
.logo {color: saddlebrown;}
.page_about .logo {color: ghostwhite;}
social-button i {}
<div class="social-button"><i></i></div>
.scrollable
a.fake
.is-expanded
.js-select
.header
.header-i
Диалект БЭМ, с более строгими правилами для максимальной надежности верстки, придуманный Вадимом Макишвили для Яндекс.Карт.
Нет миксов.
Нет модификаторов.
Есть состояния:
<div class="popup _orientation_top"></div>
<button class="button _pressed _focused"></div>
.button._pressed {}
Продвинутое использование префиксов и суффиксов от Гарри Робертса. Попытка описать взаимосвязь между независимыми блоками с точки зрения SMACSS и OOCSS.
<div class="o-media@md c-user c-user--premium">
<img src="" class="o-media__img@md c-user__photo" />
<p class="o-media__body@md c-user__bio">...</p>
</div>
БЭМ в котором можно писать как хочешь. Хоть с элементами элементов.
.block__element__subelement
Были в раннем БЭМ. Сейчас пропагандируются Гарри Робертсом и используются многими не-Яндекс разработчиками. Используются для создания своего пространства имен и логического разделения блоков.
b- ,l- ,g- ,i- ,h- ,m- ,c- и js- ,
|
qa- ,o- ,c- (другой :),u- ,t- ,s- ,is- ,has- …
|
Многим нравится зарубежный формат модификаторов, через --
, он читабельней.
<a class="block-name__element-name--state_active">
А через camelCase – ещё читабельней!
<a class="blockName__elementName--state_active">
Некоторые идут ещё дальше и заменяют __
на -
. camelCase единственный гарантирует что вы поймете где блок, а где элемент.
<a class="blockName-elementName--state_active">
Зарубежом их назвали „Individual modifiers: a shorter syntax“. У нас перевели как «Обособленные модификаторы: сокращенный синтаксис». Яндекс в официальной документации называет их «Стиль No-namespace».
<div class="blockName__elem -key_value">
.blockName {
&__elem {
&.-key_value {
}
}
}
$('.js-fancybox').fancybox();
Это миксование css-блока и js-блока на одной dom-ноде.
Канонический БЭМ считает, что они не нужны, т.к. js-функционал нет смысла отделять от блока.
Гарри Робертс и не-Яндекс разработчики их активно используют и пропагандируют: т.к. разделение позволяет легко копировать css-блок без связанного с ним JS.
Библиотека блоков от Google, css-реализации их Material Design придуманного для Android.
<!-- Accent-colored raised button with ripple -->
<button class="mdl-button mdl-js-button>
mdl-button--raised>
mdl-js-ripple-effect>
mdl-button--accent">
Button
</button>
.accordion
.accordion-item
.accordion-item-selected
.nav_bar
.nav_bar-link
.nav_bar-link-clicked
Препроцессор BEM для HTML через Grunt/Gulp
<div block="b-animals">
<div elem="cat" mod="size:big, color:red"></div>
</div>
Препроцессор BEM для HTML через PostHTML.
Синтаксис почти такой же, но с отличиями!
<div block="MadTeaParty">
<div elem="march-hare" mods="type:mad">March Hare</div>
<div elem="march-hare" mods="mad">March Hare</div>
</div>
Please use "mods" for the attribute modifiers instead of "mod" and a space as a separator of modifiers instead of a comma.
Написание BEM в Jade.
+b.block1
+e.element1 Foo
+b.block2
+e('a')(href="#bar").element Bar
+e.element2 Baz
БЭМ дает лишь базовый набор правил, конкретную реализацию и синтаксис вы выбираете сами.
Кое-что мы с вами обсудили/упомянули:
js-
блоки)(i-)
(m-)
(h-)
b-
и что такое независимый блок