БЭМ для Frontend-разработчика. 2 приема Best practice

Доброго времени суток, дорогие читатели. Рада видеть вас снова на страницах моего блога.

Сегодня речь пойдет о методологии именования CSS-классов, которая отличает новичка от разработчика с опытом. К написанию этой статеечки меня побудило мое новое место работы. Я пришла работать в одну крупную аутсорсинговую компанию, которая разрабатывает важный социальный проект на Angular. И меня чуть было не хватила кондрашка, когда я увидела вот такие классы CSS с огромной вложенностью сплошь и рядом. Что-то в духе (пример кода абстрактный, но принцип похожий):

#order .orders-mgmt .calendar-block .calendar > div.week > span.day

Дело в том, что раньше команда использовала препроцессор, разработчик был супер-профессионалом в Java, но не силен в верстке. Кодревью тоже не велся. Соответственно на выходе получился абсолютно нечитаемый индусский код.pofiksili-kod-bem

Как формируется селектор в БЭМ?

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

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

Тут казалось бы все просто — ляпай себе знай названия классов через «__» и будет тебе счастье.  По логике БЭМ всё, что является родительским элементом —  это блок, дочерний — модификатор. А что вы будете делать на практике, если вам нужно сверстать страницу? Ни о какой вложенности типа «блок__блок__элемент» не может быть и речи. Такое бездумное использование методологии — плохая практика.

В этом случае верстка формируется следующим образом:

<table className='table'>
    <thead className='table__thead'>
        <tr className='table__thead-row'>
            <th className='table__thead-row--first' rowSpan='2'>Комната</th>
            <th className='toolbar' colSpan='5'>
                <button className='btn btn__prev-month' onClick={ this.prevMonth } />
                <span className='current-date'>Июль</span>
                <button className='btn btn__next-month' onClick={ this.nextMonth } />
            </th>
        </tr>
        <tr className='week'>
            { weeks.map((w, i) => <th className='week__item' key={i}>{ w }</th>)}
            { shortWeeksDays.map((w, i) => <th className='week__item week__item--short' key={i}>{ w }</th>)}
        </tr>
    </thead>
<table>

В CSS получается каскад следующего вида:

.table {
  width: 100%;

  &__thead-row {
    color: @dark-gray;
  }

  &__head {
    display: table-cell;
  }
}

.btn {
  width: 25px;
  height: 100%;
  position: absolute;
  top: 0;
  background-color: transparent;
  border: none;
  outline: none;
  color: @dark-gray;
  cursor: pointer;

  &__prev-month {
    left: 1%;
    background: url('./img/left-arrow.png') center center no-repeat;
  }
  &__next-month {
    right: 1%;
    background: url('./img/right-arrow.png') center center no-repeat;
  }
}

И кто сказал, что препроцессоры и БЭМ несовместимы? Вы же используете в Less, Sass, SCSS и Stylus знак & для наследования. А что мешает вам просто поставить & перед «__» и не копировать вручную родительский селектор?

Когда БЭМ использовать не нужно?

В случае, если вы верстаете какой-то совсем маленький проект или лендинг, который потом 100% гарантированно не будет расширяться, а код переиспользоваться. И у вас на верстку всего 2-3 часа. Соответственно не нужно тратить время на сочинение имен селекторам и именовать их как бог на душу положит.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *