В комментах 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 руками и вы захотите его генерировать.
— Мы используем БЭМ, но не FullStack, а #b_ в CSS.
— Нет, не как в Яндексе.
— Как?
— Ну как Гарри Робертс писал…
— Как именно, он разное писал?
— Fuck.
Each time we have to understand what exactly BEM we are talking about. Both with customer and internally in the team.
НБ или просто блок, это самодостаточный элемент страницы, который при перемещении в другое место на странице или на другую страницу не теряет своей самодостаточности.
Логически и функционально независимый компонент страницы, аналог компонента в 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>
<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
БЭМ дает лишь базовый набор правил, конкретную реализацию и синтаксис вы выбираете сами.
Как автор MCSS, рекоммендую теперь уже использовать именно БЭМ. С тех пор он стал менее строгим, и более понятным. MCSS может пригодится только на очень большом, монолитном проекте.
Most common misspelling is “SMACCS”.
I should just rename it to BEM.
Кое-что мы с вами обсудили/упомянули:
js-
блоки)(i-)
(m-)
(h-)
b-
и что такое независимый блок