Форум

Методология

Инструментарий

Платформа

Сообщество

История создания БЭМ

Типичная верстка в Яндексе 2005 года

История БЭМ началась в 2005 году. Тогда, с точки зрения интерфейса, обычный проект Яндекса был набором статических HTML-страниц, которые использовались как основа для создания шаблонов на XSL.

HTML-страницы хранились в отдельной директории, которая имела подобную структуру:

about.html
index.html
…
project.css
project.js
i/
  yandex.png
  • Для каждой страницы создавался отдельный HTML-файл. В верстке использовались id и классы.
  • Скрипты хранились в одном файле для всего проекта — project.js. JavaScript использовался как вспомогательный инструмент для оживления страницы, поэтому project.js был небольшим.
  • Картинки складывались в отдельную директорию. Необходимость поддержки IE 5 и отсутствие CSS3 в браузерах, вынуждало использовать картинки для реализации любого оформления, даже для закругленных уголков.
  • Стили, как и скрипты, находились в одном файле — project.css. Для отделения стилей разных частей страницы использовались комментарии с указанием начала и конца:

    /* Content container (begin) */
        #body
        {
            font: 0.8em Arial, sans-serif;
    
            margin: 0.5em 1.95% 0.5em 2%;
        }
    /* Content container (end) */
    
    /* Graphical banner (begin) */
        .banner
        {
            text-align: center;
        }
    
        .banner a
        {
            text-decoration: none;
        }
    /* Graphical banner (end) */
    

Сверстанные статические HTML-страницы нарезались в XSL-шаблоны. Если HTML изменялся, все правки было необходимо переносить вручную в XSL. И наоборот, изменения в шаблонах требовали правок в HTML (для поддержания статического HTML в актуальном состоянии).

Зарождение основ методологии

В 2006 году началась работа над первыми большими проектами - Яндекс.Музыка и Я.ру. Эти проекты с десятками страниц выявили основные недостатки текущего подхода к разработке:

  • сложно подбирать названия классам;
  • невозможно внести изменения в код одной страницы, не затрагивая код другой.

Типичный CSS того времени, содержащий длинный каскад:

/* Albums (begin) */
    .result .albums .info
    {
        padding-right: 8.5em;
    }

    .result .albums .title
    {
        float: left;
        padding-bottom: 0.3em;
    }

    .result .albums .album .listen
    {
        float: left;
        padding: 0.3em 1em 0 1em;
    }

    .result .albums .album .buy
    {
        float: left;
        padding: 0.4em 1em 0 1.6em;
    }

    .result .albums .info i
    {
        font-size: 85%;
    }
/* Albums (end) */

Одновременное использование id и тегов:

/* Картинки на фоне (begin) */
    #foot div
    {
        height: 71px;
        background: transparent url(../i/foot-1.png) 4% 50% no-repeat;
    }

    #foot div div
    {
        background-position: 21%;
        background-image: url(../i/foot-2.png);
    }

    #foot div div div
    {
        background-position: 38%;
        background-image: url(../i/foot-3.png);
    }

    #foot div div div div
    {
        background-position: 54%;
        background-image: url(../i/foot-4.png);
    }

    #foot div div div div div
    {
        background-position: 71%;
        background-image: url(../i/foot-5.png);
    }

    #foot div div div div div div
    {
        background-position: 87%;
        background-image: url(../i/foot-6.png);
    }
/* Картинки на фоне (end) */

Верстка большого проекта была неуправляемой. Чтобы избежать этого, нужно было определить правила работы с понятиями класса, тега, визуального компонента и не только.

Появление блоков

Основное время разработчиков тратилось на создание HTML-структуры страницы и написание CSS-стилей для нее. JavaScript воспринимался лишь как сопутствующая технология.

Чтобы ускорить разработку, требовалось облегчить поддержку HTML и CSS отдельных компонентов страницы. Для этого мы ввели новое понятие – блок.

Блоком называлась часть дизайна страницы или раскладки со своим специфическим и уникальным значением, определенным семантически или визуально.

В большинстве случаев любой компонент на странице (сложный или простой) рассматривался как блок. HTML-контейнер каждого блока получал уникальный CSS-класс с тем же именем, что и у блока.

Классам блоков мы добавили префиксы (b-, c-, g-), чтобы отличать их от внутренних классов:

  • b- block Независимый блок, может использоваться в любом месте страницы.

  • с- control Контрол (независимый блок), с которым ассоциирован JavaScript-объект, обеспечивающий его функциональность. Может использоваться в любом месте страницы.

  • g- global Глобальное определение, используется по необходимости. Количество сведено к минимуму.

Кроме префиксов использовались постфиксы:

  • -nojs no javascript

Стиль применяется в отсутствие JavaScript. Если JavaScript включен, то при загрузке страницы вызывается метод init() в onload, и постфикс удаляется из всех классов. Так «включался» JavaScript для блоков.

Появление элементов

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

Ключевое различие между блоком и элементом в тот момент:

  • элемент не может существовать вне контекста родительского блока;
  • из блока нельзя извлечь ни один элемент.

Если элемент способен существовать вне блока, он становится блоком.

Позже стало возможным вынимать некоторые элементы из блока, сохраняя при этом рабочее состояние самого блока.

Элементы с большим количеством кода выделялись комментариями.

/* Head (begin) */
    .b-head { … }

    /* Logo (begin) */
        .b-head .logo { … }
        .b-head .logo a { … }
    /* Logo (end) */

    /* Right side (begin) */
    .b-head .right { … }

        /* Info (begin) */
            .b-head .info { … }
            .b-head .info .exit a { … }
        /* Info (end) */

        /* Search (begin) */
            .b-head .search { … }
            .b-head .search div div, .b-head .search div div i { … }
        /* Search (end) */
    /* Right side (end) */
/* Head (end) */

Унификация файловой структуры проекта

Разработчики интерфейсов обычно поддерживают несколько проектов одновременно. Работать с разными проектами легче, если все они имеют одинаковую (или очень похожую) файловую структуру. Поэтому мы унифицировали структуры репозиториев разных проектов.

Начали с того, что CSS, JavaScript и картинки стали складывать в отдельные директории.

JavaScript применялся все чаще, в проект подключались дополнительные компоненты и библиотеки.

Типичная структура верстки проекта 2006 года:

index.html
css/
  yaru.css
  yaru-ie.css
js/
  yaru.js
i/
  yandex.png

Основной код для IE мы писали в общем CSS-файле, например, yaru.css.

    /* Common definitions (begin) */
        body
        {
            font: 0.8em Arial, sans-serif;

            padding: 0 0 2em 0;
            background: #fff;
        }

        * html body
        {
            font-size: 80%;
        }

Специфичные правила (временные решения), работающие только в IE, создавались в отдельном файле. В имя файла добавлялся специальный указатель ie — yaru-ie.css.

    /* Common blocks (begin) */
        /* Artist (begin) */
            .b-artist .i i
            {
                top: expression(7 + (90 - this.parentNode.getElementsByTagName('img')[0].height)/2);
                filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../i/sticker-lt.png', sizingMethod='crop');
            }

Зачатки общепортального фреймворка

При верстке нескольких проектов с похожим дизайном появлялись общие блоки.

Портал Яндекса в то время содержал больше 100 разных сервисов, выполненных в одном стиле. Для такого объема данных «copy/paste» из проекта в проект уже не подходил.

Появилось общее хранилище повторно используемых компонентов, которое называлось общая библиотека блоков или просто — Common.

Первые блоки, которые вошли в Common: шапка, подвал и стили для статического текста.

Файлы блоков хранились на выделенном внутреннем сервере разработчиков (common.cloudkill.yandex.ru в примере ниже).

Это было началом работы нашего общепортального фреймворка. Cтили из него подключались в основной проектный файл при помощи импортов непосредственно с сервера:

@import url(http://common.cloudkill.yandex.ru/css/global.css);
@import url(http://common.cloudkill.yandex.ru/css/head/common.css);
@import url(http://common.cloudkill.yandex.ru/css/static-text.css);
@import url(http://common.cloudkill.yandex.ru/css/list/hlist.css);
@import url(http://common.cloudkill.yandex.ru/css/list/hlist-middot.css);
@import url(slider.css);

/* Header (begin) */
    /* Service (begin) */
        .b-head .service h1 { … }
        .b-head .service h1, .b-head .service h1 a, .b-head .service h1 b { … }

Возникла проблема: большое количество импортов замедляло загрузку страницы. Было принято решение прекомпилировать стили (и позже JavaScript-файлы) перед выкладкой.

Компиляция заменяет @import на содержимое внешних файлов (это называется inlining) и оптимизирует код: например, убирает ненужные браузеру пробелы и комментарии.

Наш внутренний инструмент для оптимизации вырос из простого Perl-скрипта в отдельный open-source-проект borschik.

Верстка независимыми блоками

К осени 2007 года правила верстки устоялись. Мы увидели практическую пользу от нового подхода, поэтому было решено рассказать об этом вне Яндекса.

На ClientSide'07 был сделан доклад про верстку независимыми блоками, которая на тот момент составляла основу наших HTML-страниц.

В докладе официально вводилось понятие блок:

Блоком будем называть фрагмент страницы, который описывается своей разметкой и стилями.

Более позднее описание.

Блоки делились на простые и составные.

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

Это было очень наивное деление: мы неоднократно сталкивались с тем, что даже в самые простые блоки вкладывались другие, и приходилось переделывать верстку. В итоге мы пришли к противоположному принципу:

Любой блок должен позволять вкладывать в него другой блок, когда это возможно.

Правила независимости блоков

Сформировались первые правила независимости блока:

  1. Для описания элемента используется class, но не id.
  2. Каждый блок имеет префикс.
  3. В таблице стилей нет классов вне блоков.

Важным решением был отказ от id. Теперь мы могли:

  • отображать на странице один и тот же блок несколько раз;
  • использовать на одном DOM-узле несколько классов (что нам пригодилось в дальнейшем).

Правила полной независимости блоков

С текущей схемой оставался ряд проблем с CSS:

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

Поэтому мы сформулировали правила более строгой независимости блоков под названием абсолютно независимые блоки (АНБ):

  1. Никогда не опираться на элементы - только на классы. .b-user b -> .b-user .first-letter

  2. Всем классам внутри блока давать имена, начинающиеся с имени этого блока. .b-user .first-letter -> .b-user-first_letter

Мы понимали, что наличие класса у каждого DOM-узла существенно увеличивает объем HTML-кода. На тот момент мы считали, что это дорого, и применяли такой подход в исключительных случаях.

Первые правила именования — префиксы

Так как распространенной проблемой в программировании является подбор имен переменным, мы решили задавать имена блоков с помощью разных префиксов с разной семантикой:

  • b- — обычные блоки;
  • h- — обертки для нескольких блоков;
  • l- — раскладки;
  • g- — глобальные стили.

Появление модификации блоков

Работая с блоками, мы поняли, что они могут иметь разные состояния. Например, блок Кнопка может быть представлен в трех состояниях: маленькая, нормальная и большая.

Вместо того, чтобы создавать три разных блока, мы начали делать модификации одного.

Модификацию мы определили как особое состояние блока или как метку, несущую определенное свойство блоку. Модификация состояла из имени (например, size) и значения (например, small, normal или big).

Возможные варианты модификации:

  1. Блок может изменить свой внешний вид в зависимости от того, где он находится. Это модификация от контекста.
  2. Можно добавить блоку второй класс. Это модификация постфиксом, она не зависит от контекста. class="b-block b-block-postfix"

Общепортальный фреймворк — Лего

Весной 2008 года была поставлена задача создать брендбук, описывающий наш портальный стиль. Решили начать работу с написания HTML/CSS кода.

Проект получил название Лего.

Структура репозитория

На верхнем уровне репозиторий разделен по технологиям:

css/
html/
js/
xml/
xsl/

Директория каждой технологии имеет свою структуру.

CSS распределяется на следующие директории:

  1. block — общепортальные блоки;
  2. util — блоки, которые имеют смысл вне Яндекса, их можно выложить в open source;
  3. service — стили для конкретных сервисов Яндекса. Подключив их к сервису, можно отобразить шапку или подвал.
css/
  block/
    b-dropdown/
      b-dropdown.css
  service/
    auto/
      block/
        b-head-logo-auto.css
      head.css
  util/
    b-hmenu/
      b-hmenu.css

Структура директории HTML аналогична CSS:

html/
  block/
    b-dropdown.html
  service/
    auto/
      l-head.html
  util/
    b-hmenu.html

JS находится в зачаточном состоянии и складывается в одну директорию:

js/
  check-is-frame.js
  check-session.js
  clean-on-focus.js
  dropdown.js
  event.add.js
  event.del.js

У каждого сервиса есть XML-файл, использующийся для построения шапки:

xml/
  block/
    b-head-tabs-communication.xml
    common-services.ru.xml
    head-messages.ru.xml
  service/
    auto/
      head.xml

XSL блоков находится в одной директории. Каждому блоку соответствует один файл:

xsl/
  block/
    b-dropdown.xsl
    b-head-line.xsl
    i-common.xsl
    i-locale.xsl
    l-foot.xsl
    l-head.xsl

Лего подключается в проекты с помощью svn:externals.

При финальной сборке проекта код библиотеки полностью включается в проект, что можно сравнить со статической линковкой.

Такой подход позволяет выпускать версии сервисов с разными версиями Лего и переходить на новую версию тогда, когда это удобно команде проекта.

CSS-файлы

CSS-файлы, подключавшиеся на страницах, состояли из @import'ов реализации блоков.

@import url(../../block/l-head/l-head.css);
@import url(../../block/b-head-logo/b-head-logo.css);
@import url(../../block/b-head-logo/b-head-logo_name.css);
@import url(block/b-head-logo-auto.css);

Эти @import'ы писались вручную.

Правила именования

Именование файлов еще не устоялось - мы пробуем разные варианты.

Общепортальный фреймворк — Лего 1.2 (2008)

Структура репозитория

В рамках версии Лего 1.2, был произведен рефакторинг, и структура репозитория проекта изменилась.

common/
  css/
  js/
  xml/
  xsl/
example/
  html/
service/
  auto/
    css/
    xml/

Убрано разделение на util и block, общий CSS находится в common/css.

От идеи выноса кода в open source на тот момент отказались и вернулись к ней только через два года.

common/
  css/
    b-dropdown/
      arr/
        b-dropdown.arr.css
        b-dropdown.arr.ie.css
        b-dropdown.css
        b-dropdown.ie.css

Всё, что находилось в опциональном CSS (файлах b-dropdown_arr.css), вынесено в директории (arr/b-dropdown.arr.css). В основном файле блока стало меньше кода.

Правила именования

Файлы для IE переименованы: указатель специфичности файла для IE был частью имени файла, а стал суффиксом. Было -ie.css, - стало .ie.css. Расширения файлов теперь могут состоять из нескольких слов.

Для модификации постфиксом вместо дефиса начали использовать подчеркивание. Это позволило визуально отделить имя блока от имени модификатора, что позже пригодилось при реализации инструментов, упрощающих работу с кодом.

Лего 2.0. Появление БЭМ

В марте 2009 года вышла версия Лего 2.0.

Этим событием оканчивается верстка независимыми блоками и начинается БЭМ.

БЭМ — аббревиатура от Блок-Элемент-Модификатор. Это три ключевых сущности, которые мы используем при разработке веб-компонентов.

Что же принципиально изменилось с выходом версии 2.0?

Основное изменение — мы вывели вперед блоки, а не технологии. Отныне блоки первичны, а технологии их реализации — вторичны.

Реализацию каждого блока разместили в отдельной директории, технологии — это файлы внутри нее. Также появилась документация к блоку — файл .wiki внутри блока.

Независимый блок

Может быть использован в любом месте страницы.

В XML блок представлен тегом в неймспейсе lego:

<lego:l-head>
<lego:b-head-logo>

HTML-класс блока соответствует имени этого тега:

<table class="l-head">
<div class="b-head-logo">

CSS-правила пишутся на класс:

.l-head
.b-head-logo

Все файлы (css, js, html, xsl), относящиеся к блоку, хранятся в его директории:

common/
  block/
    b-head-logo/
      b-head-logo.css
      b-head-logo.xsl
      b-head-logo.js
      b-head-logo.wiki

Элемент

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

В XML элемент представлен в неймспейсе lego без префикса:

<lego:b-head-logo>
    <lego:name/>
</lego:b-head-logo>

Класс в HTML соответствует имени этого тега без префикса.

<div class="b-head-logo">
    <span class="name">Авто</span>
</div>

.b-head-logo .name { ... }

Файлы элемента хранятся в отдельной директории.

common/
  block/
    b-head-logo/
      name/
        b-head-logo.name.css
        b-head-logo.name.png
        b-head-logo.name.wiki

Имена файлов элементов пишутся через точку: b-head-logo.name.css

Модификатор

Определяет внешний вид, состояние и реже поведение блока.

В XML модификатор представлен атрибутом в неймспейсе lego:

<lego:b-head-tabs lego:theme="grey">

В HTML используется дополнительный класс:

<div class="b-head-tabs b-head-tabs_grey">

.b-head-tabs_grey { ... }

Файлы для модификатора находятся в отдельной директории. Имя директории модификатора начинается с подчеркивания:

common/
    block/
        b-head-logo/
            _theme/
                b-head-logo_gray.css
                b-head-logo_gray.png
                b-head-logo_gray.wiki

Декларация используемых блоков

Все Лего-компоненты проекта описываются в XML-файле.

<lego:page>
    <lego:l-head>
        <lego:b-head-logo>
            <lego:name/>
        </lego:b-head-logo>

        <lego:b-head-tabs type="search-and-content"/>

Из него генерируются CSS-файлы.

@import url(../../common/block/global/_type/global_reset.css);
@import url(../../common/block/l-head/l-head.css);
@import url(../../common/block/b-head-logo/b-head-logo.css);
@import url(../../common/block/b-head-logo/name/b-head-logo.name.css);
@import url(../../common/block/b-head-tabs/b-head-tabs.css);
@import url(../../common/block/b-dropdown/b-dropdown.css);
@import url(../../common/block/b-dropdown/text/b-dropdown.text.css);
@import url(../../common/block/b-pseudo-link/b-pseudo-link.css);
@import url(../../common/block/b-dropdown/arrow/b-dropdown.arrow.css);
@import url(../../common/block/b-head-search/b-head-search.css);
@import url(../../common/block/b-search/b-search.css);
@import url(../../common/block/b-search/input/b-search.input.css);
@import url(../../common/block/b-search/sample/b-search.sample.css);
@import url(../../common/block/b-search/precise/b-search.precise.css);
@import url(../../common/block/b-search/button/b-search.button.css);
@import url(../../common/block/b-head-userinfo/b-head-userinfo.css);
@import url(../../common/block/b-user/b-user.css);
@import url(block/b-head-logo/b-head-logo.css);
@import url(block/b-head-search/b-head-search.css);

На примере этого файла видно, что сначала указывается общий код, а потом добавляются стили, чтобы привести Лего-блоки к дизайну проекта.

Из XML-декларации генерируются и JS-файлы.

include("../../common/block/i-locale/i-locale.js");
include("../../common/block/b-dropdown/b-dropdown.js");
include("../../common/block/b-search/sample/b-search.sample.js");
include("../../common/block/b-head-userinfo/user/b-head-userinfo.user.js");

А также XSL-файлы.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:import href="../../common/block/i-common/i-common.xsl"/>
<xsl:import href="../../common/block/i-items/i-items.xsl"/>
<xsl:import href="../../common/block/l-head/l-head.xsl"/>
<xsl:import href="../../common/block/b-head-logo/b-head-logo.xsl"/>
<xsl:import href="../../common/block/b-head-logo/name/b-head-logo.name.xsl"/>
<xsl:import href="../../common/block/b-head-tabs/b-head-tabs.xsl"/>
<xsl:import href="../../common/block/b-dropdown/b-dropdown.xsl"/>
<xsl:import href="../../common/block/b-pseudo-link/b-pseudo-link.xsl"/>
<xsl:import href="../../common/block/b-head-search/b-head-search.xsl"/>
<xsl:import href="../../common/block/b-search/b-search.xsl"/>
<xsl:import href="../../common/block/b-search/input/b-search.input.xsl"/>
<xsl:import href="../../common/block/b-search/sample/b-search.sample.xsl"/>
<xsl:import href="../../common/block/b-search/precise/b-search.precise.xsl"/>
<xsl:import href="../../common/block/b-search/button/b-search.button.xsl"/>
<xsl:import href="../../common/block/b-head-userinfo/b-head-userinfo.xsl"/>
<xsl:import href="../../common/block/b-user/b-user.xsl"/>
<xsl:import href="../../common/block/b-head-userinfo/service/b-head-userinfo.service.xsl"/>
<xsl:import href="../../common/block/b-head-userinfo/setup/b-head-userinfo.setup.xsl"/>
<xsl:import href="../../common/block/b-head-userinfo/region/b-head-userinfo.region.xsl"/>

</xsl:stylesheet>

Мы перестали писать эти файлы руками, началась генерация кода.

Скорость селекторов (2009)

При реализации новой версии Яндекс.Почты была поставлена задача сделать ее быстрой.

Для решения задачи мы начали использовать XSL в браузере (и подгружать XML, необходимый для отрисовки данных на странице). Возникла проблема: трансформации отрабатывались быстро, но вставка в DOM полученного результата происходила очень медленно. При этом, отключение CSS решало проблему.

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

Результаты исследования подробно описаны в статье.

Решение проблемы было уже готово — это абсолютно независимые блоки (АНБ).

Мы перевели все блоки в Лего на АНБ-нотацию и с тех пор создаем их так, чтобы у каждого DOM-узла был свой class, на который можно написать стили. Также мы не используем Tag Rules в CSS.

В классы элементов вносится имя блока, селекторы получаются простыми и быстрыми.

<div class="b-head-logo">
    <span class="b-head-logo__name">
        Авто
    </span>
</div>

Стабилизация нотации

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

  • В именах файлов разделитель . был заменен на __. Было b-block.elem.css — стало b-block__elem.css. Теперь они совпадают с CSS-селекторами.

  • Были реализованы модификаторы у элементов по аналогии с модификаторами блоков: .b-block__elem_theme_green по аналогии с .b-block_theme_green.

  • В имя файла модификатора и в его класс внесен тип модификатора. Было .b-menu__item_current — стало .b-menu__item_state_current. Причина этого изменения — работа с модификаторами из JavaScript.

БЭМ и open source (2010)

В 2010 году мы снова вернулись к идее open source. Мы создали организацию bem на GitHub.

Библиотека bem-bl

Мы начали выносить блоки из Лего в bem-bl, проводя одновременно с этим рефакторинг.

Параллельно с переносом блоков в новую библиотеку публиковали информацию про них.

Инструменты

Для работы с файлами по БЭМ-методам нам понадобились свои инструменты. Началась реализация инструментов bem-tools на JavaScript под Node.js.

Возникло новое понятие — уровень переопределения. Так мы стали называть директории с реализацией блоков.

Например, в проекте может быть:

  1. Публичная библиотека блоков с GitHub;
  2. Внутренняя библиотека lego;
  3. Блоки самого проекта.
bem-bl/
  b-logo/
lego/
  b-logo/
auto/
  blocks/
    b-logo/

На уровне переопределения можно задать другую схему именования директорий/файлов, отличную от нашей. Для этого нужно указать новый уровень в конфигурации:

.bem/
  level.js

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

Шаблонизатор BEMHTML

После экспериментов с разными шаблонизаторами, был разработан шаблонизатор BEMHTML, который позволяет:

  1. писать шаблоны в БЭМ-терминах;

  2. доопределять их на уровнях переопределения;

  3. исполнять эти шаблоны как на сервере, так и в браузере, поскольку шаблоны компилируются в простой и быстрый JavaScript.

Видео по BEMHTML:

Резюме

Появлению БЭМ в том виде, что мы имеем сейчас, предшествовал долгий период проб и экспериментов.

Хочется обратить ваше внимание, что на всех этапах своего развития это всё же был БЭМ.

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

Главное понять, какие плюсы БЭМ принесет в ваш проект, выбрать подходящую для вас схему и начать применять у себя!

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

Если вы заметили ошибку или хотите чем-то дополнить статью, вы всегда можете или написать нам об этом на Гитхабе, или поправить статью с помощью prose.io.