Skip to content

Latest commit

 

History

History
443 lines (327 loc) · 15.4 KB

bem.md

File metadata and controls

443 lines (327 loc) · 15.4 KB

БЭМ. Блок, Элемент, Модификатор

Статус: черновик.

Введение

БЭМ это не именование классов по определенному шаблону. Именование классов лишь способ достижения цели — «модульной верстки»

Для кого подходит БЭМ

  • Для небольших студий, у которых не один большой, а множество средних проектов
  • Фрилансера с маленькими сайтами
  • Для лендингов
  • И даже когда вы делаете правки в чужом спагетти-коде - вы можете (и должны) примерять BEM!
  • Всем остальным :)

История

БЭМ-методология: с чего всё начиналось и зачем это всё нужно

Суть БЭМ

БЭМ был придуман для решения одной проблеммы «ухода от css каскада».

Все из-за того что CSS имеет глобальную область видимости, что очень плохо.

Идея убрать каскад кажется дикой - как, это же каскад. У нас каскадные таблицы стилей! Каскад сверху до низу по всей странице! Мы в детстве 2000-х играли в игру "кто напишет меньше тегов"!

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

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

Главные правила BEM

Блок

Главное в BEM - понятие независимого блока.

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

"Как его таким написать?" Просто писать стили тупо на каждый блок. BEM хорош тем, что позволяет не забивать голову ерундой с каскадом, а сосредоточимся на семантике и логике кода. А с препроцессорами BEM позволяет писать еще и очень чистый и логичный код. Но про это чуть позже.

Как проверить? Просто навести на блок в инспекторе кода. У него не должно быть каскада.

Элемент

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

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

Модификатор

БЭМ-сущность, определяющая внешний вид, состояние и поведение блока или элемента.

Использование модификаторов опционально.

По своей сути модификаторы похожи на атрибуты в HTML. Один и тот же блок выглядит по-разному благодаря применению модификатора.

Например, внешний вид блока меню (menu) может меняться в зависимости от примененного модификатора.

Ошибки, про которые нигде не написано

Элемент элемента

<ul class="b-list">
    <li class="b-list__item">
        <a class="b-list__link">
            <i class="b-list__link__icon"></i>Text here
        </a>
    </li>
</ul>

Все есть блок

<ul class="b-list">
    <li class="b-list-item">
        <a class="b-list-link">
            <i class="b-icon"></i>Text here
        </a>
    </li>
</ul>

Элемент вне блока

<ul class="b-list">
    <li class="b-list__item">
        <a class="b-list__link">
            <i class="b-list__icon"></i>Text
            <span class="b-map__link">here</span>
        </a>
    </li>
</ul>

Контекстная зависимость блоков

.b-header
    display block
    font-size 12px

    .b-link
        color red
        &:hover
            color green

Контекстная зависимость элемента

.b-header
    display block
    font-size 12px

    .b-tabs__tab
        width 100%

Наглый модификатор элемента

.b-list__item_type_goodbye-my-eyes
    background red
    color green

    .b-list__link
        color purple

Блок, вложенный в себя

<ul class="b-list">
    <li class="b-list__item">
        <a class="b-list__link">
            <i class="b-list__icon"></i>Text here
        </a>
        <ul class="b-list">
            <li class="b-list__item">
                <a class="b-list__link">
                    <i class="b-list__icon"></i>Text here
                </a>
            </li>
        </ul>
    </li>
</ul>

Модификатор всего

<ul class="b-main-menu active"></ul>
.b-main-menu.active
    color red

Использование стилевых классов в JavaScript

var panel = $('.b-panel');
// vs
var panel = $('.js-panel');

Использование холстеров

<ul class="b-list h-mt-20 h-mb-50 h-pointer h-left h-color-red">
    <li class="b-list__item">
        <a class="b-list__link h-fs-25">
            <i class="b-list__icon"></i>Text
        </a>
    </li>
</ul>

Неиспользование холстеров

.b-list_float_left
    float left

Одноразовые элементы

<ul class="b-list">
    <li class="b-list__item">Text</li>
    <li class="b-list__item2">Text</li>
    <li class="b-list__item3">Text</li>
    <li class="b-list__item4">Text</li>
</ul>
.b-list__item
.b-list__item2
.b-list__item3
.b-list__item4
    color red

Один файл - весь код

.b-list
    list-style none

.b-list__item
    display block

.b-list__link
    color red

Oldschool reborn

.b-list
    list-style none
    li
        display block
        a
            color red

Looooooooong naming

.b-list
.b-list__item
.b-list__item-name
.b-list__item-link
.b-list__item-icon
.b-list__item-delim
.b-list__item-panel

Блоки двойники

.b-list
.b-item-list

Модификатор элементами

<ul class="b-list">
    <li class="b-list__item">
        <a class="b-list__link">
            <i class="b-list__icon"></i>Text
        </a>
    </li>
</ul>
<ul class="b-list">
    <li class="b-list__wrapper">
        <a class="b-list__panel">
            <i class="b-list__star"></i>Text
        </a>
    </li>
</ul>

Препроцессоры CSS

Для стилей удобно использовать Parent selector «&» он есть во всех популярных препроцессорах

.b-list
    list-style none

    &__item
        display block

    &__link
        color red

    &__item_active &__link
        color blue

Кроме того с недавних пор в stylus появился «Partial Reference» это что то вроде Parent parent selector

.foo
      &__bar
        width: 10px

        ^[0]:hover &
            width: 20px

трансформируется в

.foo__bar {
  width: 10px;
}

.foo:hover .foo__bar {
  width: 20px;
}

Как не прострелить себе ногу

Название блока используется только один раз

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

.block
    // стили блока

Элементы идут на втором уровне вложенности

.block
    // стили блока

    &__element
        // стили элемента

    &__title

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

.block
    &__element
        &-wrapper
            // Пример плохого элемента.
            // Его будет трудно отыскать.

Никогда не делайте подобного. Такой селектор очень трудно будет найти в коде. В примере название элемента element-wrapper разорвано на две части. Пишите название элементов полностью даже если они частично повторяют уже существующие.

Псевдо-классы, псевдо-элементы и модификаторы элементов допускается писать на третьем уровне вложенности

.block
    &__element
        &_modifier
            // стили модификатора элемента

        &_modifier_value
            // модификатор со значением не разбиваем на части

        &:hover
            // псевдо-класс — это тоже модификатор

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

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

.block
    &__element_active
        // модификатор элемента на втором уровне

    &__element_modifier_good
        // пример модификатора со значением

На практике мне больше нравится именно такая запись — модификатор на втором уровне. Также считаю, что недопустимо разбивать название модификатора на части, а так же не стоит отделять значение модификатора от его названия. Излишняя структурированность может ухудшить читаемость. Легко потерять текущий контекст. Помните об этом.

Модификаторы блока могут участвовать в каскаде и располагаются на втором уровне

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

.block
    background white
    &__title
        color black
        font-weight bold

    &_featured
        background black

    &_featured &__title
        color white
        font-size 30px

Изящность кода чуть теряется из-за того, что нам важно сохранить значение &. Как только мы перейдём на следующий уровень вложенности, то использовать его в названии элемента уже не сможем — нужно будет писать полное название селектора вместе с названием блока, чего мы всячески избегаем.

.block {
  background: white;
}
.block__title {
  color: black;
  font-weight: bold;
}
.block_featured {
  background: black;
}
.block_featured .block__title {
  color: white;
  font-size: 30px;
}

Именование классов

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

В оригинальном стиле такая строка будет выглядить следующим образом:

block[_blockModName[_blockModVal]][__elemName[_elemModName[_elemModVal]]]

(В квадратных скобках необязательные параметры)

  • block-name — блок.
  • block-name_mod-name_mod-val — модификатор блока в формате ключ-значение.
  • block-name_mod — булевый модификатор блока.
  • block-name__elem-name — элемент блока.
  • block-name__elem-name_mod-name_mod-val — модификатор элемента в формате ключ-значение.
  • block-name__elem_mod — булевый модификатор элемента.