Головокружительное погружение в БЭМ
«Что означают
— один из самых
часто задаваемых мне вопросов.--
и __
в названиях ваших классов?»
Ответом будет — спасибо БЭМ и Николасу Галлахеру…
БЭМ — аббревиатура от слов Блок, Элемент, Модификатор — методология именования, изобретённая парнями из Яндекса. Это изящный путь именования классов с целью сделать их понятнее и прозрачнее для других разработчиков. Этот способ строг и информативен, что делает БЭМ идеальной системой для групп разработчиков на больших проектах.
Важно отметить, что я использую систему именования основанную на БЭМ, но изменённую в соответствии с предложениями Николаса Галлахера. Система именования, освещаемая в текущем посте, это не оригинальный БЭМ, a улучшенная его версия, которая мне нравится больше. Тем не менее, в независимости от фактических изменений в обозначениях, улучшенная версия основана на тех же принципах БЭМ.
Система именования использует такой шаблон:
.block{}
.block__element{}
.block--modifier{}
.block
— самый высокий уровень абстракции компонента..block__element
— дочерний элемент.block
помогающий поддерживать его целостность..block--modifier
— другое состояние или версия.block
.
Двойные символы используются вместо одиночных из-за того, что класс может быть сам по себе разделён дефисом, например:
.site-search{} /* Блок */
.site-search__field{} /* Элемент */
.site-search--full{} /* Модификатор */
Цель БЭМ — рассказать другим разработчикам как можно больше о том, что делает кусок кода, только по названиям классов в разметке. Читая HTML с небольшим количеством классов внутри, вы можете увидеть взаимодействия во всем коде и между его частями; что-то может быть компонентом, что-то дочерним элементом — элементом этого компонента, а что-то может быть измененной копией — модификатором компонента.
Подумайте как следующие селекторы могут быть связаны:
.person{}
.person__hand{}
.person--female{}
.person--female__hand{}
.person__hand--left{}
Верхний блок это человек (.person
), имеющий элементы, к примеру руки
(.hand
). Человек может быть разным, например женского пола (.female
), и эта
вариация, в свою очередь имеет свои элементы. Ещё раз, тоже самое, но записанное
в «обычном» CSS:
.person{}
.hand{}
.female{}
.female-hand{}
.left-hand{}
Все эти классы имеют смысл, но выглядят несколько разобщёнными. Рассмотрим
.female
; к чему относится класс female
? Что насчёт .hand
? Может быть это
дверная ручка или письменная? Используя БЭМ мы предоставляем разработчикам
не только более подробную, но и более точную информацию; мы устанавливаем связи
между элементами за счет одного только именования классов. Очень круто.
Давайте рассмотрим пример формы поиска на сайте ещё раз:
<form class="site-search full">
<input type="text" class="field">
<input type="Submit" value ="Search" class="button">
</form>
Это обычные классы, по ним много не скажешь. Да, мы вполне можем так работать, но с БЭМ мы получим:
<form class="site-search site-search--full">
<input type="text" class="site-search__field">
<input type="Submit" value ="Search" class="site-search__button">
</form>
Теперь видно, что у нас есть блок названный .site-search
, у которого есть
вложенный элемент .site-search__field
. Также наглядно видно, что существует
модификации блока .site-search
имеющая свой собственный класс
.site-search--full
.
Давайте рассмотрим ещё один пример…
Если вы знакомы с OOCSS, то не возникнет трудностей и с абстракцией медиа объекта.
Обретая форму БЭМ, медиа объект выглядит так:
.media{}
.media__img{}
.media__img--rev{}
.media__body{}
Используя такой способ записи стилей, мы уже знаем, что .media__img
и
.media__body
находят внутри .media
и то, что .media__img--rev
это
небольшая модификация .media__img
. И это информация полученная только по
названиям селекторов!
Другим плюсом является ясность взаимосвязей внутри разметки. Рассмотрим пример с медиа объектом ещё раз:
<div class="media">
<img src="logo.png" alt="Логотип «Рога и копыта»" class="img-rev">
<div class="body">
<h3 class="alpha">Добро пожаловать в компанию «Рога и копыта»</h3>
<p class="lede">«Рога и копыта» — молодая, динамично развивающаяся компания</p>
</div>
</div>
Из этого кода, мы никогда не сможем понять как классы .media
и .alpha
относятся к друг другу. Да и относятся ли? А что насчёт классов .body
, .lede
или .img-rev
и .media
? Из этого HTML кода невозможно представить, что есть
компонент сам по себе, а что есть дополнительные элементы и опции. Если мы
изменим код в соответствии с нотацией БЭМ:
<div class="media">
<img src="logo.png" alt="Логотип «Рога и копыта»" class="media__img--rev">
<div class="media__body">
<h3 class="alpha">Добро пожаловать в компанию «Рога и копыта»</h3>
<p class="lede">«Рога и копыта» — молодая, динамично развивающаяся компания</p>
</div>
</div>
Теперь мы сразу видим, что .media
— блок, а .media__img--rev
элемент блока
.media
, этот элемент также имеет модификатор; ясно видно, что .media__body
—
неизменённый элемент блока .media
. Вся картина взаимосвязей успешно
складывается по именам классов. Это невероятно удобно и полезно.
Безобразный код
Одним из часто встречающихся аргументов против использования БЭМ является то, что он — уродлив; осмелюсь сказать, что если вы отказываетесь от использования кода, опираясь на то как он выглядит - вы просто не улавливаете сути. Если код тяжело читать и поддерживать и для этого нет достаточных оснований, то стоит задуматься, а стоит ли его использовать, но если код просто «выглядит странно», но если для этого есть веская причина, то стоит все взвесить, прежде чем от него отказываться
Я согласен с тем, что БЭМ выглядит немного странно, но возможности, которые он дает намного перевешивают недостатки, связанные с его внешним видом.
БЭМ может выглядеть смешным — и он вынудит вас больше печатать (большинство редакторов имеют автодополнение, а минификация скроет разницу в размерах файлов) — но он очень мощный.
БЭМ’ить или не БЭМ’ить?
Я использую БЭМ синтаксис в любом проекте, который создаю, и он каждый раз доказывает свою полезность. Я призываю всех подумать о принятии БЭМ, потому что он крепче связывает CSS и HTML, и позволяет создавать легко поддерживаемый код не только для команды, но и для самого себя спустя полгода.
Тем не менее, при использовании БЭМ, важно помнить, что нет нужды использовать его повсюду, например:
.caps{ text-transform:uppercase; }
Этот CSS никогда не поместить в БЭМ методологию, это просто одиночное правило.
Еще один пример пример:
.site-logo{}
Это наш логотип; он может быть преобразован так:
.header{}
.header__logo{}
Но это необязательно. Фишка БЭМ’а в правильном распределении дочерних элементов. На самом деле не все вложенные элементы являются БЭМ элементами. В примере с шапкой сайта и логотипом, логотип находится в шапке, но это не мешает ему с легкостью оказаться в одной из колонок или в подвале сайта. Пространство имён БЭМ элемента может начаться в любом месте, поэтому будьте аккуратны и применяйте БЭМ только в тех местах, в которых он нужен.
Например:
<div class="content">
<h1 class="content__headline">Можно предположить, что лемма проецирует…</h1>
</div>
Возможно нам нужно было назвать второй класс .headline
; это зависит от того,
зависит ли оформление от того, что заголовок находится в .content
или
он просто случайно оказался в .content
области. Если второе, то в этом
примере вам БЭМ не нужен.
Абсолютно всё готово к изменению под БЭМ. Рассмотрев пример с логотипом ещё раз, представьте, что вы хотите сделать праздничную версию логотипа для рождественского дизайна сайта. Мы можем сделать так:
.site-logo{}
.site-logo--xmas{}
Мы можем быстро создавать разные варианты, используя --
синтаксис модификатора.
Самое трудное в БЭМ — выбор, когда начать и когда закончить пространство очередного блока и вопрос о необходимости использования методологии в каждом конкретном случае. Это одни из тех случаев, когда понимание придёт само.
Подведем итоги
Вот он БЭМ (или его небольшая модификация); Полезное, мощное и простое соглашение по именованию, которое позволит сделать код более читабельным и понятным, упростить работу с ним и его масштабирование, сделать его более надежным и намного более строгим.
Все те, для кого БЭМ выглядит немного странно, имейте в виду — это весьма ценное дополнение в список инструментов фронтэнд разработчика, в не зависимости от проекта.