Как стать автором
Обновить

Комментарии 172

Вот таких туториалов и не хватает, ИМХО, чтобы распространить БЭМ. Спасибо.
Замечу, что мне очень сильно не нравится стиль описания классов вида: .my-super-main-list__item, .b-footer-logo__copyright. То есть, идея БЭМ мне нравится, а вот реализация — нет.
В БЭМ настраивается стиль. По хорошему, надо писать сразу в bemjson/bemhtml/css/js, из которых уже собирается конечная страница. И в таком случае, можно настроить все эти разделители.
Суть не в разделителях.

Суть вот в таких конструкциях: class="b-link b-link_white b-link_block b-link_undecorate" (из примера в статье).

Чем это, по существу, отличается от style="color: #fff; display: block; text-decoration: none;"?

Специфичностью.

Вы создаете inline стиль, который имеют самую высокую специфичность.
Вы не можете повторно использовать данный код. Возьмите большие сайты, которые развиваются постоянно.

ИМХО, специфичность здесь ни при чём.

Проблема здесь в том, что эти модификаторы слишком низкоуровневые и действительно эквивалентны inline-стилям, а значит не нужны.

Гораздо лучше было бы модификаторы делать более высокоуровневые — например, b-link_primary, b-link_secondary, b-link_inverted-background в которых стиль ссылок соответствует семантике, а не деталям реализации.

Хороший тест для проверки этого свойства — это придумать хотя бы 2 различные реализации модификатора. Для b-link_primary их бесчисленное множество, в зависимости от стиля сайта. Для b-link_white или b-link_undecorate — только одна.
БЭМ — это методология не более, а сокращение кода решается с помощью препроцессоров.

Например вот такую конструкцию:

div.b-footer__logo
    div.&__img


Можно транслировать в:

<div class="b-footer__logo">
      <div class="b-footer__logo__img">
                ....
      </div>
</div>


Из минусов:
— написание собственного препроцессора
— усложняется поиск элемента грепом и его автоматическая замена
— требуется поддержка синтаксиса в редакторах
Никому это не нравится, поэтому в bem-tools или enb html генерируется из шаблонов, а при написании стилей используются препроцессоры. Ну и идея длинных имён в том, что с одного взгляда понятно, к какому блоку принадлежит элемент или модификатор. И как сделать лучше лично я еще не придумал.
БЭМ — это интересная технология, но достаточно сложная в описании (при всей ее внутренней простоте). До сих помню первый вопрос из зала на Я.Субботнике в Минске после доклада по БЭМ: «Я так и не понял, так что такое БЭМ?»
Конечно, чувак про сео был :)
«Честный веб-мастер» который? :)
БЭМ предполагает уход от каскадных стилей (типа div .someClass li)

Будет ли в БЭМ считаться исключением такой вариант, когда нужно при наведении курсором на блок изменить свойства элемента?
.block:hover .block__element { /* ... */ }
Если говорить вкратце, то основная идея БЭМ — это полный отказ от каскадов и любых цепочек классов.

Однако, как отмечают в яндексе: «Не обязательно использовать БЭМ ровно в том виде, в котором он предлагается».
Соответственно, здесь вопрос относится к тому — какое соглашение принято в Вашей компании (либо лично Вами)
Полного отказа от каскада нельзя избежать. Каскад нужен, если задан модификатор у блока и нужно менять внешний вид/поведение у вложенных элементов, как в примере выше.

С другой стороны, надо понимать, что использование каскада влечёт за собой сложности при вкладывании блоков один в другой.

При такой структуре

block_theme_blue
another-block
block

по каскаду будут затронуты так же элементы внутреннего вложенного блока, что скорее всего не предполагалось при разработке.
Зачем исключения?

.block__element:hover { }
В таком случае свойства не изменятся для братьев.
Идея заключалось в том, чтобы при наведении курсором на блок .block изменялись свойства для всех его потомков .block__element.
У меня для вас хорошие новости. Они и будут изменяться. Потомки. Все.
Будут, но не одновременно.
Допустим мне надо при наведении курсора на блок изменить цвет всех заголовков в данном блоке, что вы предлагаете?
НЛО прилетело и опубликовало эту надпись здесь
Я спокойно отношусь к использованию каскада внутри блока. Но нетерпим к межблочному каскаду, либо когда пишут каскад ради каскада (даже если вы не пишете стили по БЭМ), т.е.

.block .block__text {}

терпимо, а

.block .link {}
или
.block .block__content .block__item .block__text {}

ужасно.

Даже в первом случае у нас в будущем могут быть проблемы с этим блоком при внесении изменений, но часто проще и быстрее делать именно так.
НЛО прилетело и опубликовало эту надпись здесь
Да вы хитрец!
Именно для таких вещей и был разработан БЭМ, чтобы вместо этого ада —
 .menu {
    > a {
      &.active {
        background: blue;
      }
    }
  }


Было:
.b-menu-link-active
{
        background: blue;
}

НЛО прилетело и опубликовало эту надпись здесь
Вы опять идете на каскад. Идея, сама СУТЬ БЭМа — уйти от каскада. Этот код переписывается и Вы освобождаетесь от каскада.
В БЭМ вы переплачиваете за размер «букоф», выигрывая на этапе отрисовки веб-страниц: использование классов БЕЗ каскада позволяет браузерам быстрее применять стили -> пользователь быстрее получает запрашиваемую страницу.
НЛО прилетело и опубликовало эту надпись здесь
БЭМ — это как раз про разделение на модули, так что классы не идут лапшой.
Ну, мне кажется, тут вы лукавите. Если уйти от каскада, то каждый новый блок должен быть со стандартным шрифтом (Times New Roman чаще всего), стандартным размером, станартным box-sizing и т.п.

Мне кажется, во всём нужна мера. Таким образом, чтобы использовать каскад, надо добиваться того, чтобы каждый новый уровень расширял или переопределял нижний уровень.

a {
    text-decoration: none;
}
— нормально (если вы хотите отказаться от подчёркиваний ссылок во всём проекте… ну и «порадовать» сами_знаете_кого),
a {
    text-decoration: none;
    padding: 40px;
    background-color: black;
    color: white;
}
— плохо, т.к. существует почти 100%-ная вероятность, что вам понадобятся обычные текстовые ссылки без паддингов и фонов.

Т.е. если использовать каскад для расширения, то никакие БЭМ не нужны:
.panel {
    display: block;
}
.panel-sm {
    font-size: 12px;
    padding: 20px;
}
.panel-md {
    font-size: 14px;
}
.panel-dark {
    background-color: #444;
    color: #ccc;
}
.panel-dark a {
    color: #fff;
}


<div class="panel panel-sm panel-dark">...</div>


Имхо, правильный каскад с миксинами намного более удобен и гибок.
.b-menu {
  margin: 10px;
  position: relative;
  transition: all .5s;
  color: green;

  &-link {
    position: relative;
    transition: all .5s;
    color: green;

    &-active {
      position: relative;
      transition: all .5s;
      color: green;
    }
  }
}
Ваш пример в стайлусе:
.b-menu
  margin: 10px;
  position: relative;
  transition: all .5s;
  color: green;

  &__link 
    position: relative;
    transition: all .5s;
    color: green;

    &_active
      position: relative;
      transition: all .5s;
      color: green;
Тоже так по началу писал, но потом отказаля от этой идеи, т.к. в файлах с большой вложенностью блоков ориентироваться невозможно, да найти нужный класс не зная проект весьма сложно.
В листинге ведь максимальная вложенность блоков: здесь и Б и Э и М. Хорошо, можно добавить ещё медиавыражение. Глобальный поиск возможен только по блоку, конечно, но я никогда не сталкивался с проектами, где это было бы проблемой из-за количества элементов у блока.
НЛО прилетело и опубликовало эту надпись здесь
Александр, если под элементами вы сейчас имеете в виду блоки (ведь только так есть противоречия моему комментарию), то действительно — плюс одна вложенность. Но в таком случае добавляется прямой каскад вместо независимого элемента с модификатором &__link_vertical:
&_vertical &__link 
    color: pink;
Если разбивать файлы по блокам на файловой системе, то эта проблема становится не такой большой.
НЛО прилетело и опубликовало эту надпись здесь
Во-первых, существуют компании, которые при написании веб-страниц пользуются методологией, но не пользуются инструментами bemjson и т.п.

Затем, как подчеркивал в статье — БЭМ используется для сайтов, которые имеют >20-30 уникальных страниц. Когда блоки могут повторяться и т.п.

Сайты, которые имеют > 20-30 уникальных страниц, прекрасно себя чувствуют и без БЭМ. И блоки можно повторно использовать применяя существующие практики и не прибегая к помощи БЭМ.

Применять или не применять БЭМ — это выбор компании (или группы разработчиков). Нельзя говорить, что это, более «хороший» (или, по крайней мере, структурированный) подход. Это ваше субъективное мнение.

В остальном, для желающих изучить и применять БЭМ, хорошая статья.
НЛО прилетело и опубликовало эту надпись здесь
Старую верстку в новом дизайне, при условии что она сделано нормально, использую только частично и только в тех местах, где новый дизайн предусматривает схожие элементы со старым дизайном. Чем вам БЭМ поможет при новом дизайне?

Но давайте посмотрим на другой вариант. Взять тот же Twitter Bootstrap (просто как пример). Если вы его внедряли в проект (заказанный на полный редизайн), вы в нем сильно что-то меняли? Вот вам пример хорошей верстки не по БЭМ, с большим количеством реюзабельных блоков. И применять его можно для сайтов с > 20 страниц очень даже запросто.

Я не отрицаю использование БЭМ. Если вам он подходит, то хорошо. Но говорить, что это «более хороший подход к верстке» — это субъективное мнение.
НЛО прилетело и опубликовало эту надпись здесь
Как не увидели? Я же написал, что частично могу использовать старую верстку, при условии, что она выполнена нормально и при условии, что новый дизайн содержит схожие элементы со старым дизайном.
Если это не ответ на ваш вопрос, то значит я не правильно понял ваш вопрос.
Если Вы приходите в компанию, где работают без БЭМ и их продуктом является таки веб-сервис, то у них почти всегда есть концепция построения проекта. Иначе держать всю структуру просто-таки невозможно.
Вот тут полностью согласен. Концепция построения проекта обязана быть. Иначе хаос. И если это БЭМ, то значит, по каким то причинам, он подходит компании. Но БЭМ — это очередная методология и она не самая лучшая, но, стоит отметить, и не самая худшая.
а какие методологии, похожие на БЭМ, вы ещё подразумеваете в сравнении?
Я не правильно применил термин «методология». Более правильно было бы выразиться — «техники верстки» (а статья именно о верстке). Я понимаю, что БЭМ шире, чем просто верстка.

И я хотел сказать, что, как минимум, существуют SMACSS и OOCSS. Лично для меня (я не говорю, что это более хороший подход) больше подходит техника OOCSS, которая имеет схожие черты с вашим БЭМ, но которая не подталкивает давать классы практически всем элементам. Я просто не вижу необходимости настолько усложнять процесс верстки (ИМХО).

Зачем давать классы всем элементам:
clubs.ya.ru/bem/338
НЛО прилетело и опубликовало эту надпись здесь
Не согласен, это как раз первый шаг в понимании и начало освоения БЭМ как методологии. Я CSS 2 года писал в терминах БЭМ, и никому это фатальных неудобств не доставляло. А для меня и других верстальщиков было удобно разговаривать на одном языке, поддерживать вёрстку друг друга и свободно взаимодействовать.
Я тоже так думал несколько лет назад.
Ну вот я сколько не пробовал — так и не понял в чем его «фишка» по сравнению с тем-же XSLT или любым другим шаблонизатором.

Ведь любой более-менее устоявшийся шаблонизатор позволяет каскадировать шаблоны, строить из них иерархии, использовать блоки и т.д.

Плюсы те-же:
  • изменили блок — поменялось везде
  • иерархия блоков
  • зависимости
  • реюзабельность блоков
  • возможность иметь библиотеку блоков

Ну и т.д.

И не надо ничего описывать в json-ах — все внутри блоков, если блок состоит из других блоков — то они так-же соберутся при вызове основного.

А шаблонизатор можно применять как к html, так и к js и css — главное правильно испольозвать наименование — и все.

Так можно делать свои контролы аля select2 — в шаблоне всего-лишь что-то наподобие <% include /blocks/customSelect %>, а шаблонизатор сам поймет что сюда надо засунуть /blocks/customSelect/body.tpl и сгенерирует для сборщика, что на данной странице в js надо добавить /blocks/customSelect/body.js, а в css /blocks/customSelect/body.css.

Отказ от наследования классов с моей точки зрения ужасен — отказываться в угоду скорости можно на проектах уровня yandex.market, а в обычных, коих 90% каков смысл отходить от столь удобного инструмента как каскадирование CSS?

Если Вы применяете профессионально БЭМ, и Вам не сложно — объясните — чем он лучше? И в чем все-таки его главный козырь?

Может я действительно не понимаю его сути?
НЛО прилетело и опубликовало эту надпись здесь
Ну, во-первых данный стиль именования можно заюзать на любом шаблонизаторе, в БЭМ это не упирается.

Во-вторых Есть несколько способов избавляться от такой штуки с CSS — например юзать во всех подчиненных классах в начале верхнее имя иерархии, типа ..., или же использовать иначе это называется — использовать всегда для блока уникальные имена.

Но самое главное — незаисимвые блоки != БЭМ, их можно делать с моей точки зрения абсолютно на любом шаблонизаторе, о чем я выше и написал.
Почитайте историю БЭМ.
БЭМ == Независимые блоки.

Изначальное название БЭМ: Верстка на независимых блоках (точное название не припомню, но суть эта)
Мне кажется, в 2006 (или 2005?) году статья на вашем сайте выглядела немного иначе. Про с- там кажется ничего не было, а было про h- (holster).
Не слышали разницу понятий «необходимое условие» и «достаточное условие»?
НЛО прилетело и опубликовало эту надпись здесь
Ниже ответ был дан xnim — мое заблуждение было в том, что я считал БЭМ прежде всего шаблонизатором со своей методологией, а это просто методология.
НЛО прилетело и опубликовало эту надпись здесь
Вы сейчас говорите о шаблонизаторах. Однако БЭМ это не шаблонизатор. Это методология написания html\css кода.
Это такая же методология, как, например, SMACSS или OOCSS (весьма популярные технологии разработки html\css кода)

Многие компании используют XSLT шаблонизатор + БЭМ методологию.

БЭМ описывает то, как организовывать структуру HTML кода, чтобы добиться ее переносимости и плавного расширения.

В проектах без БЭМ (а если быть более точным — без методологии разработки), зачастую случается следующего рода проблема — создан сайт. Затем появляется необходимость поправить расположение блока меню, блок регистрации поменять местами с лого. Используя БЭМ вы отлично знаете, что, чтобы поменять местами достаточно сменить стили у элементов блока хедер (если говорить о примере в статье) Если необходимо сменить цвет — Вам не надо лезть в код и менять что-то там. Достаточно лишь добавить нужный модификатор. Код становится гибким.

Отказ от наследования…
В статье писал, что может случиться, если Вы в блок добавите вложенный элемент с тем же названием, что и для тех, кои были раньше. БЭМ это учитывает, а в проекте построенном на каскаде может потребоваться переписать код (пример есть в статье)

Хм, я всегда почему-то считал, что БЭМ это все-таки инструмент, т.е. да, методология, но в контексте конкретных инструментов для нее. Возможно в этом причина моего непонимания.

Окей.
Однако возвращаясь к каскадированию — ведь можно делать так чтобы блоки были рабочими и независимыми не откзываясь от каскадирования, а просто соблюдая ряд правил.

Естественно если писать body div то это тихий ужас :-D

Ну а если применять единое устаявшееся правило именования, то,, например я не вижу конфликтов.
Инструменты для БЭМ были разработаны много позже методологии.

БЭМ предлагает правила именования. В этом его прелесть — разработчикам не нужно «искать то какой принцип исопльзовал предыдущий разработчик при именовании»

Я думаю, Вам будет очень интересна дискуссия в статье здесь — marow.net/archives/161

Для данного треда вынесу цитату:
«Каждый их разработчиков, рано или поздно приходит к чему-то подобному БЭМу»

Возвращаясь к каскадированию — вы вправе использовать его внутри одного блока, например. Все зависит от принятых соглашений для проекта

Также добавлю, если посмотреть на SMACSS — он очень похож на БЭМ.
Спасибо огромное за статью — действительно более-менее понятно стало.
Стоит почитать ещё историю развития БЭМ:
ru.bem.info/method/history/
Еще исходя из опыта своего вот что странное вырисовывается при разработке сайта.

«Тот самый крутой плюс ради чего все и затевалось» — реюзабельности — в сайтах нет.
Практически. ИМХО.

Если не брать в расчет контролы (типа автоподборщика, календариков, поиска и т.д.).

Обычно сайты живут очень простой жизнью — они пишутся под компанию на определнном этапе развития ее бизнеса, они решают потребности в данный конкретный момент времени.

И да — чуть-чуть допиливаются до тех пор, пока компанию не шагнет на ступеньку выше (ну или не умрет).

Если она шагнула — обычно идет полное переписывание сайта, т.к. адаптация старого к новому развившемуся бизнесу гораздо сложнее.
Плюс убивается такой заяц, как редизайн.

Я работал на многих проектах, как для больших компаний, так и для средних и мелких и везде это повторялось.

В веб-проектах, корпоративном бэкофисе — да, там реюзабельность существует, а вот на сайтах я с ней практически не столкнулся.

У всех так? Или мне только так везло? Стоит заморачиваться на сайтах с версткой независимыми блоками, если не брать в расчет контролы?
Я думаю, что стоит. Яндекс (могу ошибаться) никогда кардинально не менял всю верстку. Используется как старая, так и новая. (по мере наработки — спасибо независимым блокам)

Далее, такие сайты как lenta.ru — постоянно дорабатывают сайт -> без независимости постоянно бы вставал вопрос о «переписки»

hh.ru -использует БЭМ + XSLT — аналогично использование наработок позволяет использовать заново блоки -> сокращается время разработки.
Ну я эти сайты подразумевал под «веб-проектами» — там — да. Ибо одна и та-же идея, бизнес-модель практически не меняется.
Для сайтов, которых цель — бложик или статика, либо форумы (подобное им) БЭМ не нужен.(читать как не является нужным) Так как такие сайты создаются один раз и следующий раз изменятся только при редизайне.
Ок, ну а сайты компаний?
Я про них как раз писал.

Они тоже обычно создаются один раз, т.к. создаются под конкретную бизнес-модель и точно так-же редко меняются до полного редизайна, который обычно заключается в полном обновлении всего и вся, вклшючая сервер-сайд.
В таком случае разработчику стоит решить использовать БЭМ или нет. Так как острой необходимости здесь не будет.

Единственная вещь, которую можно записать в «стоит» — это следование единому стилю оформлению
Для независимости блоков делаем классы без каскада, хорошо, но почему для элементов нельзя применять каскад от класса блока, ведь они уже зависимы от своего блока? И модификаторы также.
Независимость зависима от решений, что считать блоками?
Приводится пример: «с БЭМ легко перенести блок из левой колонки в правую». А что если этот «блок» при проектировании считался элементом для колонки? Значит элементов в обще не должно быть, каждый тег — независимый блок. Каждому тегу свой класс?

Прочитайте, пожалуйста, статью. Я привожу пример и рассказываю, что же такое блоки и что такое элементы
Имя пользователя используется в разных виджетах хабра, в статьях, комментах… Но вы посчитали его элементом, я его бы делал блоком.
Я его выделил как элемент внутри блока. Сам по себе он может быть также блоком.
Яркий пример — верстка меню — есть блок меню, который включает элементы — пункты меню, которые включают в себя блок — ссылка
Рискну спросить: если мы хотим сделать вложенный блок, его нужно засовывать в элемент?
Строго следуя БЭМ — да
Нет, её будет отдельный блок, который можно использовать где угодно.
У элемента могут быть элементы?
Нет
Великолепно.
Очень полезно и нужно!

Буквально на днях собирался вспомнить, как оно делается, а тут эта статья.
Спасибо вам, автор!
<div class="b-networks__icon b-networks__icon_small  b-networks__icon_instagram"></div>

Тут даже инлайн стиль короче будет написать чем такую лапшу в коде держать (может даже еще быстрее отработает его браузер чем каскад)
Вы напишите вместо b-networks__icon_small инлайн стиль типа width: 16px. Ок. А потом маленькая иконка станет шириной 15px — и в случае инлайна вас ждет жесткий find + replace all, в одном месте указать width: 15px не получится.
С таким подходом к именованию классов я могу вообще в верстку не заглядывать — работать только с css стилями, впрочем так и поступаю, разрабатывая универсальные html блоки с классами, которые копируются из проекта в проект практически не в тронутом виде.
Любая методология хороша до тех пор, пока ею не заинтересовались фанбои или какая-нибудь контора, желающая подчеркнуть свой авторитет (что вполне равнозначно).

Любой нормальный верстальщик в те или иные моменты пользуется каким-либо из средств, которые здесь перечислены для своих нужд.
А какими-то — очень часто. Например, независимыми блоками. Скажем, я видел (и сам пару раз так делал — способ-то очень логичный) как при добавлении новой порции функций к сайту, который разрабатывали совсем другие люди, новые блоки верстались совершенно отдельно, в пустой странице, с отдельными стилями и т.п., но с обязательной каскадностью (препроцессоры там не использовались, но всем селекторам было просто добавлен в начале id родительского блока, правило для самого контейнера блока выполняло при этом функцию reset-а, экранируя содержимое блока от стилей сайта и управляя его позиционированием). Дальше программисту оставалось только подключить стиль и вставить код блока в шаблон, заменив текст переменными. Верстальщик при этом вообще ни разу не взглянул на верстку остального сайта.

И никому не приходило в голову называть это особым словом и пропагандировать это в сети, люди просто работали так, как им удобно в конкретный момент.
Т.е. если в курпном проекте вдруг появятся два блока с одинаковыми названиями классов, но разными стилями оформления, то вся эта методология коту под хвост и нужно добавлять модификаторы и переписывать стили одному из блоков? Или я что-то не так понял.
У разных блоков разные имена. Если же появляется элемент интерфейса, совсем немного отличающийся от уже существующего, то можно взять готовый блок и добавить ему модификатор, всё верно.
В том-то и дело, что БЭМ, добавляя каждому тегу много презентационных классов и усложняя их названия, не дает никаких преимуществ и независимости блоку. Потому-что нет гарантии что этот класс уже где-то не используется и ваш стиль не сломает верстку в другом месте.
Я решил познакомиться с этой методологией, потомучто все говорят о независимости блоков, но я этого не увидел к сожалению.
Единственно верным методом для меня осталась семантическая верстка с одним классом для создания пространства имен. Как в примере ниже комментарий.
По сути блок — это и есть пространство имён. В этом пространстве задаются модификаторы и могут быть вложены элементы.
Проблема одноимённых пространств имён есть всегда.
Проблема одноимённых пространств имён есть всегда.

Так пропаганда идет что БЭМ решает эту проблему, а на самом деле нет, лишь усложняет верстку.
Возьмём блок a, у него есть элемент header. И ещё блок b, у него тоже есть элемент header.

Получится такой css:

.a {}
    .a__header {}

.b {}
    .b__header {}


У каждого блока элемент header может выглядеть абсолютно по-разному, но иметь одинаковое название.
Разве это не каскадом?
Ладно, не будем начинать священную войну. Я свой выбор сделал и для себя решил самообманом не заниматься.
Единственное что может решить поблему независимости — это класс со случайным названием в 256 бит вида <a class='sjica3c...' href=..., но это уже хардкор.
БЭМ — это не только про CSS, это ещё и про JS, шаблонизацию, файловую структуру и про сборку проекта, поэтому очень удобно оперировать именно такими сущностями.

А если сделать каскад:
.a .header {}

то получится, что это селектор на блок header, который вложен в блок a. Но так писать не стоит, потому что теряется смысл независимости блоков.
НЛО прилетело и опубликовало эту надпись здесь
Где вы увидели каскад в классах .a__header и .b__header?
В том-то и дело, что БЭМ, добавляя каждому тегу много презентационных классов и усложняя их названия, не дает никаких преимуществ и независимости блоку.
Где вы увидели в БЭМ рекомендацию добавлять презентационные классы?

Имена сущностям надо подбирать так, чтобы они отражали суть, а не то, как оно выглядит.
Особенно такой ужас начнет плодиться при росте последователей БЭМ. Раньше при интеграции проектов могли нарваться на одинаковый класс .link, а потом .b-link. А если g-класс разный? Ууу…
Поддерживаю комментарий выше, этот БЕМ похож на Inline-style, только на классах, не вижу смысла в таком количестве классов, если тут все можно решить просто семантической версткой:

Чем это лучше обычной верстки?

<footer>
<div class="b-twitter">
           <h3> TWITTER FEED</h3>
           <time>22 oct</time>
           <p>In ultricies pellentesque massa a porta. Aliquam ipsum enim, hendrerit ut porta nec, ullamcorper et nulla. In eget mi dui, sit amet scelerisque nunc. </p>
</div>
</footer>
Яндекс проводил тестирование, что классы при рендере работают быстрее чем ID.
Чтобы уйти от ID они начали пользоваться классами, классов стало много и чтобы привести в порядок кашу классов придумали БЭМ.

.button .inactive{ } работает медленнее чем .button{} .button__inactive{}, каскады в правилах CSS тоже медленнее рендерятся чем разные правила.

В ответ на ваш вопрос производительностью рендера страницы.

Для себя лично выбрал SASS: для блока указывается id внутри блока каскад, лично для меня это более наглядно и просто в использовании.
Сомнительная производительность, при таком подходе мы раздуваем и html и css код, что уменьшает отклик еще при загрузке сайта.

Да и экономить в производительности CSS, ну не знаю. Inline наверное будет еще быстрей и даже короче :)
Вот и у меня напросился тот же самый вывод.
Я люблю короткие и лаконичные решения. Compass + минимальный HTML как раз то что мне подходит.
Думается мне, что разница в производительности CSS мизерна и даже не стоит обсуждения в сравнении с тем, что пожирает JS. Исключая разве что какие-то особо клинические случаи.

Это напоминает баянистые разговоры про якобы медленность селектора *, поутихшие вот только недавно. Угу, поставить звездочку это значит медленно, а перечислить в файле reset.css все возможные html-теги через запятую — это окей, это хорошо.
clubs.ya.ru/bem/338

Погоняйте в своих браузерах приведённые в тексте тесты.
Усреднил по нескольким попыткам:
FF 25: 130/220 мс соответственно
Chrome 31: 210/240 мс
IE 10: 240/250 мс

То есть в абсолютном выражении на сегодняшний день разница невелика. Но дело даже не в этом.
Главное в том, что ваш тест — тот самый искусственный клинический случай. Стили в нём нарочно написаны предельно неоптимально, а 30 тысяч дивов на практике не встречается никогда.
Например, результаты поиска на ebay (причем я специально включил максимальное число товаров на страницу) имеют DOM с 7-8к узлов. Развесистая статья на smashingmagazine с двумя сотнями комментариев ~6к.
Время ответа сервера, загрузки картинок и обработки JS просто проглотит время обработки CSS.
НЛО прилетело и опубликовало эту надпись здесь
Про одностраничные приложения я в общем-то согласен, но ещё раз напоминаю об искусственной переусложненности того теста.
В реальной жизни цифры меньше в несколько раз. Например, сейчас посмотрел, веб-интерфейс Gmail оперирует 6-9к узлов, в Google Docs около 5к.

Вот, правда, Яндекс-почта, имея сразу после загрузки ~3к, в процессе хождения по папкам и письмам растет практически неограниченно — мне удалось достигнуть 40к и наверное это не предел (но опять-таки, для этого пришлось совершить действий гораздо больше, чем я делаю в реальной жизни). Наверное, потому у Яндекса и встает проблема CSS-производительности там, где другие её избегают :)
НЛО прилетело и опубликовало эту надпись здесь
Что и требовалось доказать. Мы специально работали над этим.
Хотелось бы увидеть ваш ответ на habrahabr.ru/post/203440/#comment_7028578 и habrahabr.ru/post/203440/#comment_7028034, а не только там где вас похвалили.
Насчет Я.Почты — пока выглядит так, что ошибка проектирования решена переусложнением верстки (впрочем, с использованием имевшейся методологии).
Я не занимаюсь разработкой ЯПочты, поэтому не могу прокомментировать.
20 мс в свежеоткрытом виде?
НЛО прилетело и опубликовало эту надпись здесь
Если вам достаточно написать вручную HTML, по-быстрому накидать CSS и не менять регулярно внешний вид страницы, то можно обойтись традиционным подходом.

Как родилась методология БЭМ и зачем делать всё так сложно — об этом хорошо рассказывает Сергей Бережной в своём докладе на YaC 2011: video.yandex.ru/users/ya-events/view/387/
Объясните логику префикса b-. Я понимаю и одобряю префикс js-, в целом не против префикса g-, но префикс b-… Да он у каждого элемента! Соответственно можно легко отказаться от него, приняв за основу тот факт, что все классы относятся к структуре документа, если не указано иное.
Я думаю, у человека просто привычка. Взгляните на современные open-source библиотеки Яндекса, выполненные по БЭМ — там сложно найти вообще какие бы то ни было префиксы.
НЛО прилетело и опубликовало эту надпись здесь
Префиксы полезны в процессе постепенного перевода сайта с лапши на бэм, гарантированно не пересекаются со старыми классами. Когда всё становится бэм — можно спокойно от них отказаться
Неоспоримое преимущество БЭМ в том виде, каком он описан Яндексом — строгая формализация. Не менее очевидный недостаток — очень громоздкие и избыточные цепочки классов. Поэтому он — удел очень крупных проектов в которых:
а) крайне важна стандартизуемость
б) пишутся очень большой командой
в) активно применяются средства автоматической генерации (писать это врукопашную — полный мазохизм).

В «обычной жизни» я использую что-то типа лайт-БЭМ-а — принцип тот же, но имена классов гораздо короче и читабельнее. То есть, например, вместо:
b-slide-list__item
b-slide-list__item_active

будет что-то вроде
.slider-item
.slider-item-active
Наверное, кому-то эта технология подойдет, но мне не понравилось. Я не очень понимаю, зачем тащить страницу вместе с контентом в JSON?
На мой вкус, в масс-проектах (об уровне Яндекса сейчас не говорю) удобнее и практичнее просто использовать CSS-препроцессоры, а верстать всё же в HTML.
HTML — это ассемблер для веба. :)
Когда я верстал hunterboat.ru/ — дизайн менялся уже после сдачи макета, но мне не нужно было переколбашивать тонны html и
вручную разбираться в css-классах.

И более подробно в статье ru.bem.info/libs/bem-core/1.0.0/bemhtml/rationale/
Многие используют другие шаблонизаторы для генерации html. Я слышал про priv.js, bemtree, jade. Ну и если просто фигачить html-странички, вёрстка со временем очень быстро устареват и поддерживать её в актуальном состоянии становится очень трудно.
Отдельно хотел бы обратить вот на какое преимущество БЭМа, а именно, на примере использования с разными CMS. Довелось мне как-то внедрять верстку на малоизвестную CMS Diem (на базе Symfony 1.4). Дело в том, что там многое завязано на то, что многое можно делать с помощью drag'n'drop в процессе редактирования блоков в интерактивном режиме. Как результат, огромное количество всяких оберток, от которых никуда не деться. Типичный пример:
<div id="dm_page">
 	<div class="dm_layout"> 
	<div class="dm_area dm_layout_top" id="dm_area_19"><div class="dm_zones clearfix"><div class="dm_zone"><div class="dm_widgets"><div class="dm_widget main_header"><div class="dm_widget_inner">
  .....

Ужасно, конечно. Но наш верстальщик привык все верстать независимыми блоками. И когда я внедрил его верстку в это безобразие, обнаружил, что все выглядит просто отлично с самого начала! И даже при перетаскивании блоков в режиме интерактивного редактирования ничего нигде не ломалось. При использовании каскадов, все могло бы быть намного сложнее.
Никита, спасибо вам большое за эту статью. Вы — пример для других хабраюзеров. Вы не только написали комментарий к существующей статье, но еще и своей статьёй подробно объяснили эту методологию, объяснив все ее достоинства и недостатки.
P.S. Странно, что еще никто про uppercase не написал ;)
Касательно БЭМа, его приверженцев и системы минусования (я рискую, но не могу не спросить): «Часто ли вы сталкиваетесь с тем, что негативно отзываясь о технологии авторитетной компании, вам ставят минус в карму, а сами посты или комментарии плюсуются»?

Это означает, что с вами соглашаются люди, но не любители того, о чем вы отозвались негативно. Это банальное занудство, мол «ты обидел БЭМ», а я тебе наср… у в карму. Очень логично и обоснованно, прямо детский сад какой-то))). Я высказываю свое мнение, обосновываю его, а вы срет… е.

Чем то это напоминает высказывание из недавнего поста «Вечный торт: интервью с Денисом Крючковым, основателем Хабрахабра»: «Хочешь быть объективным и писать обо всем? Будь готов к тому, что придется многое выворачивать наружу и не всем это понравится. Разумеется, такое далеко не всем нравится. Приходишь к людям и говоришь: «Купите у меня рекламу», а они отвечают: «Нет, мы не станем покупать у тебя рекламу, потому что ты написал вот об этом, а тебя просили этого не делать». Так я довел себя до ручки и продал проект, не успев из него даже уйти.» Точно по тому же принципу вас и минусуют.

Не пора ли ввести систему обоснования минуса в карму (именно в карму)? И если это банальная обида на то, что вы «обижаете высокотехнологичную методологию», то ограничиваться только этим обоснованием. Не могут все быть «хомячками и пресмыкающимися».
Никита,

большое тебе спасибо за статью! Очень полезная и интересная!!!

Будет очень круто, если ты напишешь про нее пост со ссылкой в нашем БЭМ-клубе на Я.Ру и в группе на Фейсбуке. Написали в твиттер, но в эти места лучше б ты сам (пусть знают в лицо автора!).

Если аккаунтов нет, то дай знать, я опубликую.
спасибо, что запостил :)
Меня одного в БЭМе смущает, что по названию блока невозможно понять с первого взгляда что же он всё-таки делает?

<div class="b-networks__icon b-networks__icon_small  b-networks__icon_rss"></div>

Вместо «сети-рсс» здесь написано: «блок сети с иконкой и блок сети с иконкой маленький и блок сети с иконкой рсс».
В БЭМе?
Названия блоков придуманы автором статьи, при чем здесь методология?
Это смущает многих. Но это вы описали не самый худший вариант. На главной страницы Яндекса есть и сложнее.
Вряд ли там вручную css пишется, есть же BEMJSON+BEMHTML ru.bem.info/libs/bem-core/1.0.0/bemhtml/rationale/
И модификаторы являются индикаторами состояния, то есть css-класс button_disabled_yes не навешивается руками — это происходит в js-фреймворке i-bem ru.bem.info/libs/bem-core/1.0.0/i-bem.js/bem-js-main-terms/
Не путай, пожалуйста, конкретную реализацию у конкретного автора с общей методологией.
Ну я смотрю здесь лица из Яндекса тусуются и никто не против, статья чуть ли не на bem_ru зафичерена — вот я и позволил себе сделать выводы. Ты же понимаешь, что я сейчас не про светлую идею, я про реализацию в умах 90% адептов.
Если придерживаться синтаксиса БЭМ, то у автора можно найти ошибки. Например, в
.b-networks__icon_small
потеряно определение модификатора, вместо этого сразу идёт его значение. А должно быть так:
.b-networks__icon_size_small
Т.е. название-блока__название-элемента_название-модификатора_значение-модификатора. Сам по началу допускал такую ошибку, поэтому теперь её замечаю :)

Пруф на оф.сайте:
Мы используем одно подчёркивание для отделение имени модификатора от имени блока и ещё одно подчёркивание для отделения значения модификатора от его имени.


В этом плане он похож на предыдущий пост, ссылку на который автор привёл в самом начале — вроде бы начинание похвальное, подробная инструкция для новичков, но написано изначально неверно — тут мелочи в синтаксисе, в предыдущей статье некоторые теги не совпадают с указанным доктайпом и т.д.
В новой библиотеке bem-core, допускаются булевы модификаторы, об этом есть упоминание здесь: ru.bem.info/libs/bem-core/1.0.0/i-bem.js/i-bem-js/
Плохо что автор как образец показывает классы вида block__element__element (b-slider-case-element__number) и модификаторы не в формате modifer-value (b-slider-case-element__number_active).

Это самая главная проблема с из-за которой идёт неприятие bem у других — им кажется что bem — это «длинные бездумные классы повторяющие dom-вложенность». Это не так. По bem нельзя писать block__element__element, @harisov негодует: twitter.com/harisov/status/403421669974618112

Ещё конечно стоило написать о миксовании, различных видах модификации (от контента и переопределением), рассказать про абстрактные блоки, и если уже пошли говорить за префиксы и упомянули никогда не существовавший в пределах Яндекса префикс js-, то стоит написать и про префиксы i- как минимум, а заодно можно и про l-, h- и т.д.

Напишу статью-ответ, где разберу типичные ошибки с bem.
Про BEM написано хорошо, а вот сама верстка очень неаккуратная и со спорными моментами. Вот некоторые замечания:

— Возникает вопрос о xml-валидности кода и общей стандартизации: почему-то часть одиночных тегов написана с закрывающим слешем, а другая часть без. Я за то, чтобы везде писать /.

— Тег meta написан в коротком html5-стиле, а link по-старому.

— Очень прыгают стили и верстка: лишние пустые строчки, пробелы после двоеточия в css, вперемешку tab и пробелы, двойные пробелы и т.п.

— С фоном для .b-page кажется фейл: background-color не применится к этому блоку, так как идущий дальше background вернет это свойство к значению по-умолчанию. Пример на jsfiddle. Уже писал про использование общего свойства background и font в комментарии к посту Mirantus

— Очень удивило, что кнопка GO сделана div'ом и все это не находится в form.

— Излишнее количество классов для ссылок в основном меню. Также, семантически правильно считается оформлять меню в виде списка ul>li.

— Нет ни слова о проблеме с floating-элементами и в верстке это не учитывается.

Очень похоже, что верстка нигде не тестировалась, а писалась по-быстрому прямо в хабраредакторе :) Поэтому, есть большие сомнения, что в готовом виде она будет работать и выглядеть как на картинке (и это даже забыв про IE). Мне кажется, что для обучающих статей, рассчитанных на новичков, особенно важно уделять внимание деталям.

js- (JavaScript) префикс для выделения элементов для селекторов js
Так делать не нужно. По БЭМ js это одна из технологий блока и скрипты пишутся в рамках уже имеющихся блоков, а не плодятся другие.
b-link b-link_menu b-link_menu_active

это лучше писать как b-link b-menu__link b-menu__link_active_yes

Т.е. мы не расширяем блок b-link знанием про меню, а наоборот в рамках меню делаем элемент __link. Это более специфично получается.

Вообще про миксы стоит посмотреть доклад Кира:
tech.yandex.ru/events/yasubbotnik/msk-sep-2012/talks/327/
Благодарю!
О данном (не знаю, как точно определить..) ходе не предполагал.
Может, очевидность спрошу, но ни в статье ни в комментариях не нашел ответа.

Почему независимость блоков не достигается родным CSS-селектором ">"? В чем выигрыш БЭМа по сравнению с конструкцией
.block > .element { }
?
НЛО прилетело и опубликовало эту надпись здесь
1) Ощутимо медленный по сравнению с прочими тормозами отрисовки страницы? Может, есть ссылки на статьи по теме?
2) Как я понял, элемент не содержит других элементов, если не является блоком. А если даже вложен, то чем плохи решения:
.block > .subblock { }
.subblock > .subelement { }
или
.block > .subblock  { 
  > .subelement { }
}
?

Первое решение — и без вложенности и подчеркивает независимость блоков. Почти БЭМ, только в другой записи.
Элемент блока не обязательно вложен в блок.
На уровне DOM-дерева элемент может содержать в себе все, что угодно — и другие блоки, и другие элементы.
<div class="first-block__element"></div>
<div class="first-block"></div>
<div class="second-block">
      <div class="second-block__first-element">
            <div class="second-block__second-element"></div>
            <div class="some-another-block"></div>
      </div>
</div>


Автор комментария имел в виду, что элементы не могут содержать в себе элементов на семантическом уровне.
НЛО прилетело и опубликовало эту надпись здесь
т.е. вас не смущает тот факт, что конструкция <a href=""></a> настолько спецефична и неприменима ни в чем другом, кроме как в ссылках, и по факту вы не сможете без нее организовать ссылки (не стоит только умничать про обработку любого элемента JS'ом) и поэтому вы предлагаете к крайне спецефичной конструкции применить супермегаспецифичный стиль, на случай «Вдруг в будущем откажутся от использования ссылок, а мы будем на коне».

Более логично в данном случае использовать класс .menu, потому что меню можно на чем угодно реализовать (и это факт) — div. nav, ul, span, да хоть p, а ссылки оставить ссылками

.menu a {
color: red;
}

Почему нет оператора наследования >? да потому что не факт что ссылки в меню окажутся родственниками в первом колене.

Ну и по поводу приведенной статьи — вы на полном серьезе отсылаете к статье 13 летней давности для оценки производительности?
НЛО прилетело и опубликовало эту надпись здесь
Вот так можно лаконично описать этот блок в BEMJSON:

    ({
        block: 'menu',
        content: [
            {
                elem: 'item',
                content: {
                    elem: 'link',
                    content: 'test',
                    url: '#'
                }
            },
            {
                elem: 'item',
                mods: { active: true },
                content: {
                    elem: 'link',
                    content: 'test',
                    url: '#'
                }
            },
            {
                elem: 'item',
                content: {
                    elem: 'link',
                    content: 'test',
                    url: '#'
                }
            },
            {
                elem: 'item',
                content: {
                    elem: 'link',
                    content: 'test',
                    url: '#'
                }
            }
        ]

    })


И, согласно разделению логики представления и данных, сделать соответствующий BEMHTML-шаблон:
(Понятие предиката в BEMHTML-шаблоне похоже по смыслу на селектор в CSS htmlbook.ru/test/selector)


/**
* Общий шаблон для блока 'menu'
*/
block('menu')(

    tag()('ul'),

    elem('item')(

        tag()('li')
    ),

    elem('link')(

        tag()('a'),

        attrs()(
            {
                href: this.ctx.url
            }
        )
    )
)


/** Шаблон для блока 'menu'  с учетом модификатора "активный" у вложенного элемента :
 *
 * "если блок содержит элемент 'item' с модификатором 'active',
 * то установить у блока свойство '_active_item'
 *
 * @predicate block('menu').elem('item').elemMod('active', true)
 *
 */
block('menu').elem('item').elemMod('active', true)(
    /* в моде def (не путать с модификатором, мода -- правило генерации html)
     * applyNext:
     * установить свойство шаблона для блока _active_item равное true и
     * применить следующий шаблон
     *
      * */
    def()(
            applyNext({_active_item: true}
        )
    )
)

/** Шаблон для блока 'menu' с установленным свойством '_active_item':
 * для блока со свойством '_active_item' элемент 'link' генерировать через тег 'span'
 *
 * @predicate block('menu').match(this._active_item).elem('link').tag()
 */
block('menu').match(this._active_item).elem('link').tag()('span')

НЛО прилетело и опубликовало эту надпись здесь
Развернутая структура выглядит немного многословной, но зато наглядно.
А BEMHTML согласен, на непривычный взгляд странно выглядит.
антиреклама на 5 баллов!
За это инструменты БЭМ и боятся. Лаконично это пишется разве что с Emmet с БЭМ-фильтром, как-нибудь так: .menu>.__item*5>.__link, но поддерживать потом всё равно придется полную версию, конечно.
Да, к сожалению, порог входа выше, чем «писать html».
В течении столетий прогрессивное человечество приходило к тому, что для удобного восприятия материала необходимы какие-то правила. Книга делится на страницы, у всех одинаковая структура, текст набирается одним шрифтом, везде одинаковые отступы, материал расположен по сетке. Если есть исключения для акцентирования на чем-то внимания, то они не многочисленны. Внутренние части подчиняются общему. Так построен CSS. Но тут пришел Яндекс и решил, что у его дизайнеров избыток творчества и все эти правила слишком ограничивают. И еще он решил, что блок, взятый неизвестно откуда, не должен подчиняться правилам страницы, на которой находится, а должен быть сам по себе. Так появился БЭМ.

Не знаю-не знаю, мне кажется, что в идеальном мире будет свойство no-inherit, запрещающее наследование любых свойств от родителя, а БЭМа в идеальном мире не будет.
НЛО прилетело и опубликовало эту надпись здесь
Я же не про читаемость кода, а про читаемость сайта. Хорошо, когда на сайте, например, все ссылки одного цвета, тогда пользователь сразу их распознает. Если же дизайнер-верстальщик вдруг захотел сделать в своем блоке какую-нибудь особую няшную ссылку, пусть заслуженно помучается
НЛО прилетело и опубликовало эту надпись здесь
Интересно, спасибо за статью, давно слышал про bem и благодаря вашей статье наконец узнал что и как это на деле. Только я бы наверное избегал модификаторов вида *_blue, *_underline и т.п.
Спасибо за статью.
На bem.info нашел вот такой код:

.menu_size_big {
  // CSS code to specify height
}
.menu_type_buttons .menu__item {
  // CSS code to change item's look
}


Т.е. иногда все таки каскад можно? Или только в зависимости от контекста? Или опечатка?
НЛО прилетело и опубликовало эту надпись здесь
Без зависимости никак. Приведу пример. Есть блок, в его элементе второй блок.

<div class="block">
    <div class="block__element">
        <div class="block2">Text</div>
    </div>
</div>


В какой-то момент первому блоку добавляется модификатор (состояние) block_select_on, что он выделен:

<div class="block block_select_on">
    <div class="block__element">
        <div class="block2">Text</div>
    </div>
</div>


Блок в состоянии выделения, допустим, меняет фон на чёрный. У второго блока фон прозрачный, но цвет его текста желательно поменять на белый. Как в BEM в зависимости от состояния первого блока поменять стиль второго блока?

Варианты:

  1. Блоки независимы, можно считать проблемы нет. Второму блоку нужно задать свой фон. И пофиг какое состояние у первого блока. Получим неадекватный дизайн. Для полной независимости нужно всем блокам определять все свойства стиля, иначе ложно утверждение, что блок везде будет выглядит одинакового (не поедет его стиль). Но тогда не применить множество классов на тег.
  2. Второму блоку тоже добавляем модификатор (свой), чтоб менял цвет и фон. Хм. Кто его будет добавлять? Логика первого блока? Но блоки независимы, т.е. нет знаний, какие блоки могут оказаться внутри первого и от куда узнать, какие им модификаторы добавлять? Пробуем каким-то образом обрабатывать событие выделения логикой второго блока, чтобы он сам себе модификатор добавлял. Но и тут проблема независимости. Изначально неизвестно внутри какого блока окажется второй блок и, соответственно, при каких событиях добавлять модификатор? Сам модификатор по смыслу зависим от первого блока. И от куда второй блок должен знать, что ему нужно именно в черный цвет краситься? Опять зависимость от первого блока.

  3. Применяем каскад. .block_select_on .block2{} Где писать этот каскад, в css первого, второго блока или в css проекта? Ладно, на уровне css/html получается лаконично. Но где желаемая независимость блоков? Разработчик первого блока ещё может догадаться, что в его блок будут добавлять другие блоки, и им нужно менять оформление, но неизвестно что именно менять (структура блоков неизвестна). Разработчик второго блока даже и не думал об особенностях отображения внутри неопределенных им блоков.


Мы хотим независимость, когда всё пропитано зависимостью? Каков компромисс?

  1. Классы BEM быстрее обрабатываются. Стараемся не использовать каскад
  2. CSS BEM независим от структуры HTML. И в целом меньше проблем со стилями вложенных блоков
  3. Каскад применяется там, где BEM неприменим, где зависимость от конекста. Но мне до сих пор не понятно, как это урегулировано в самом BEM и его инструментах. Как в BEMJSON указать такую зависимость?
  4. Необходима база именованный блоков для соблюдения уникальности и возможности взять за основу существующий блок
  5. Грабли с применением jQuery и других скриптов. Например, не можем с легкостью добавить любой кнопке состояние нажатия (класс), так как название модификатора состоит из имени блока. Приходится использовать дополнительные обертки.
  6. Чтобы оформление хоть как-то зависело от темы, необходимо добавлять в HTML своего блока классы базовых блоков. Например button, input, title. Но здесь проходит тонкая грань независимости, нужно предполагать, что определяют классы базовых блоков.
  7. Вместо каскада работаем с длинными перечнем классов в теге.


НЛО прилетело и опубликовало эту надпись здесь
Глядя на реальный проект, из которого придуман пример, не могу согласится, что это глобальный модификатор. Это модификатор конкретного блока (первого). В нём он имеет смысл, определяет поведение и внешность блока. В других блоках в любых уровнях он не нужен или будет иметь другой смысл. Тут явная зависимость от родительского блока. Могут быть примеры с большой вложенностью, где модификатор влияет только на непосредственных детей или с какой-то там структурой. Это всё решается каскадом, да, с вытекающей из этого зависимостью блоков. Я, собственно, о том, что от зависимости не уйти, применяется ли БЭМ или нет.

Всем, кто хочет улучшить свою верстку я бы только рекомендовал минимизировать какскад, применять соглашения об именовании классов и не жертвовать совместимостью со всем, что в вебе напридумывали и придумают ещё. Полностью следуя методологии BEM и применяя её инструменты, ощущаю себя в песочнице отстраненным от прогресса :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации