Все, кто следил за мной или моей работой на протяжении какого-либо времени, бесспорно знают, что я огромный фанат соглашения о наименованиях БЭМ. То, о чем я расскажу в этой статье, является не альтернативным или другим соглашением о наименованиях БЭМ, а дополнением к нему: небольшими добавками, которые поднимут БЭМ на ступеньку выше. Этот расширенный синтаксис БЭМ окрестили BEMIT, так как он включает некоторые парадигмы и шаблоны из (еще неопубликованной) архитектуры CSS в виде перевернутого треугольника (ITCSS). BEM + ITCSS = BEMIT.

Вспомним, что такое БЭМ – он работает за счет разбивки всех классов в базе кода на три группы:

• Блок: Единственный корневой элемент компонента.
• Элемент: Составная часть Блока.
• Модификатор: Вариант или расширения Блока.

Блоки, Элементы и Модификаторы: БЭМ. Абсолютно любой класс в проекте подпадает под одну из этих категорий, и именно поэтому БЭМ так хорош – он невероятно прост и прямолинеен.

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

<div class="media  user  premium">
  <img src="" alt="" class="img  photo  avatar" />
  <p class="body  bio">...</p>
</div>


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

<div class="media  user  user--premium">
  <img src="" alt="" class="media__img  user__photo  avatar" />
  <p class="media__body  user__bio">...</p>
</div>


Здесь мы точно видим, что user, user--premium, user__photo и user__bio связаны между собой. Также мы видим, что media, media__img и media__body также связаны между собой, а avatar – это одинокий Блок, у которого нет Элементов и Модификаторов.

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

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

С этой точки зрения я решил расширить БЭМ и сделать BEMIT. BEMIT не добавляет новые виды классов – у нас все равно остаются только Блоки, Элементы или Модификаторы, но при этом он добавляет информацию об использовании и состоянии.

Пространства имен



Наиболее распространенные виды пространств имен – это c- для Компонентов, o- для Объектов, u- для Утилит и is-/has- для состояний (более подробно это описано в статье, на которую я ссылаюсь). С учетом этого, вышеприведенный HTML должен быть переписан следующим образом:

<div class="o-media  c-user  c-user--premium">
  <img src="" alt="" class="o-media__img  c-user__photo  c-avatar" />
  <p class="o-media__body  c-user__bio">...</p>
</div>


Исходя из этого, я вижу, что у нас есть повторно используемая абстракция в медиа-объекте (o-media*) и два компонента реализации (c-user* и c-avatar). Эти классы все равно остаются Блоками, Элементами или Модификаторами: к ним не добавлена новая классификация, но добавлен новый уровень значения.

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

Отзывчивые суффиксы


Следующее, что BEMIT добавляет в традиционный БЭМ-нейминг, это отзывчивые суффиксы. Эти суффиксы принимают формат @<контрольная точка>, и сообщают нам этот класс в следующем размере:

<div class="o-media@md  c-user  c-user--premium">
  <img src="" alt="" class="o-media__img@md  c-user__photo  c-avatar" />
  <p class="o-media__body@md  c-user__bio">...</p>
</div>


Здесь мы имеем o-media@md, что означает, что медиа-объект будет в этой контрольной точке. Другие возможные примеры:

• u-hidden@print – класс утилиты, скрывающий элементы при печати.
• u-1/4@lg – утилита, которая отображает объекты в четверть ширины в большой контрольной точке
• o-layout@md – объект макета в средней контрольной точке.

Знак @ — это понятный человеку и логический способ указывать условные состояния. Он позволяет разработчикам узнавать о любых потенциальных перестановках или внешнем виде этой части рассматриваемого UI с первого взгляда.

Замечание: Не следует использовать символ @ в файле CSS в следующем виде:

@media print {

  .u-hidden\@print {
    display: none;
  }

}


Проверка работоспособности


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

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

/**
 * Outline для всех классов.
 */
[class] {
  outline: 5px solid lightgrey;
}

/**
 * Outline всех BEM-элементов.
 */
[class*="__"] {
  outline: 5px solid grey;
}

/**
 * Outline всех BEM Модификаторов.
 */
[class*="--"] {
  outline: 5px solid darkgrey;
}

/**
 * Outline для всех классов объектов.
 */
[class^="o-"],
[class*=" o-"] {
  outline: 5px solid orange;
}

/**
 * Outline для всех классов компонентов.
 */
[class^="c-"],
[class*=" c-"] {
  outline: 5px solid cyan;
}

/**
 * Outline для всех "классов отзывчивости".
 */
[class*="@"] {
  outline: 5px solid rosybrown;
}

/**
 * Outline для все "Hack classes".
 */
[class^="_"] {
  outline: 5px solid red;
}


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

Мы можем запустить проверку работоспособности различными способами, но самый простой – это вложение всего объема в класс Scope:

.s-healthcheck {

  ...

  /**
   * Outline all Responsive classes.
   */
  [class*="@"] {
    outline: 5px solid rosybrown;
  }

  ...

}


…который потом можно добавлять в элемент html, когда вам нужно включить проверку:

<html class="s-healthcheck">


В заключение


У нас есть несколько простых дополнений к БЭМ, которые превращают его в BEMIT: добавление информации в начало и конец стандартного класс Блок, Элемент или Модификатор, чтобы предоставить нам больше данных о том, как классы себя ведут в неотносительном смысле. Еще несколько примеров:

.c-page-head {}

@media screen and (min-width: 15em) {
  .u-text-center\@sm {}
}

.o-layout__item {}

@media print {
  .u-color-black\@print {}
}



Комментарии (3)


  1. vintage
    12.08.2015 10:37
    +3

    В БЭМ изначально тоже были префиксы типа, но потом от них отказались.

    u-1/4@lg
    perl в моём css? :-)

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

    Например, если бы я попросил вас удалить все классы, связанные с пользователями, в следующем фрагменте HTML, от которых вы бы избавились?
    Очень странная задача.


  1. norlin
    12.08.2015 10:55
    +1

    Про префиксы уже написали – в БЭМ они были/есть (никто не мешает вам их использовать).
    Насчёт суффиксов – не очень понял, какой в них смысл и чем они отличаются от модификаторов.


  1. rajdee
    12.08.2015 14:23

    Честно говоря, это и изначально на БЭМ не очень похоже, а с предложенным новым синтаксисом и вовсе — ад.