Архитектура CSS: блочный элемент-модификатор (БЭМ) и атомарный CSS

  1. Блок-элемент-модификатор (БЭМ)
  2. Дело против атомного CSS
  3. БЭМ против атомного CSS
  4. Знай, когда идти своим путем

Ниже приводится небольшая выдержка из новой книги Тиффани: Мастер CSS, 2-е издание ,

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

Блок-элемент-модификатор (БЭМ)

BEM или Block-Element-Modifier - это методология, система именования и набор связанных инструментов. Создан в Яндекс BEM был разработан для быстрой разработки значительными командами разработчиков. В этом разделе мы сосредоточимся на концепции и системе имен.

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

Возможно, это сбивает с толку, «блок» здесь относится к сегментам HTML, которые составляют страницу или приложение

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

Блок нижнего колонтитула может содержать блок карты сайта

Более гранулированный элемент, чем блок. Как БЭМ документация объясняет :

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

Например, блок формы поиска содержит элемент ввода текста и элемент кнопки отправки, как показано на рисунке ниже. (Чтобы уточнить, мы используем «элемент» в смысле элемента дизайна, а не в смысле элемента HTML.)

)

С другой стороны, основной блок контента может иметь блок списка статей. Этот блок списка статей может содержать серию рекламных блоков. И каждый рекламный блок статьи может содержать элементы изображения, выдержки и «Читать далее», как показано ниже.

И каждый рекламный блок статьи может содержать элементы изображения, выдержки и «Читать далее», как показано ниже

Вместе блоки и элементы составляют основу соглашения об именах БЭМ. По правилам БЭМ:

  • имена блоков должны быть уникальными в рамках проекта
  • имена элементов должны быть уникальными в пределах блока
  • вариации блока - скажем, окно поиска с темным фоном - должны добавить модификатор к имени класса

Имена блоков и имен элементов обычно разделяются двойным подчеркиванием (.block__element). Имена блоков и элементов обычно отделяются от имен модификаторов двойным дефисом (например, .block - модификатор или .block__element - модификатор).

Вот как выглядит БЭМ на примере формы поиска:

<form class = "search"> <div class = "search__wrapper"> <label for = "s" class = "search__label"> Искать: </ label> <input type = "text" id = "s" class = "search__input"> <button type = "submit" class = "search__submit"> Поиск </ button> </ div> </ form>

Вариант этой формы с темным фоном может использовать следующую разметку:

<form class = "search search - inverse"> <div class = "search__wrapper search__wrapper - inverse"> <label for = "s" class = "search__label search_label - inverse"> Поиск: </ label> <input type = "text" id = "s" class = "search__input search__input - inverse"> <button type = "submit" class = "search__submit search__submit - inverse"> Поиск </ button> </ div> </ form>

Наш CSS может выглядеть так:

.search {color: # 333; } .search - inverse {color: #fff; фон: # 333; } .search__submit {background: # 333; граница: 0; цвет: #fff; высота: 2рем; дисплей: встроенный блок; } .search__submit - inverse {color: # 333; фон: #ccc; }

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

У этого подхода есть несколько преимуществ:

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

В БЭМ гораздо больше, чем можно удобно разместить в разделе главы. Сайт BEM описывает эту методологию более подробно, а также содержит инструменты и учебные пособия, которые помогут вам начать работу. Чтобы узнать больше об аспекте соглашения об именах в BEM, еще один фантастический ресурс Получить БЭМ ,

Если БЭМ - индустрия, Атомный CSS - его мятежный персонаж. Названный и объясненный Тьерри Кобленцем из Yahoo в его статье 2013 года: Оспаривание лучших практик CSS «Атомный CSS использует узкую библиотеку имен классов. Эти имена классов часто сокращены и отделены от содержимого, на которое они влияют. В системе Atomic CSS вы можете сказать, что делает имя класса, но нет никакой связи между именами классов (по крайней мере, не теми, которые используются в таблице стилей) и типами контента.

Давайте проиллюстрируем на примере. Ниже приведен набор правил, которые мы могли бы назвать традиционной архитектурой CSS. В этих наборах правил используются имена классов, которые описывают содержимое, к которому они применяются - глобальное окно сообщения и стили для окон сообщения «успех», «предупреждение» и «ошибка»:

.msg {background-color: # a6d5fa; граница: 2px solid # 2196f3; радиус границы: 10 пикселей; семейство шрифтов: без засечек; отступы: 10 пикселей; } .msg-success {background-color: #aedbaf; граница: 2px solid # 4caf50; } .msg-warning {background-color: # ffe8a5; цвет границы: # ffc107; } .msg-error {background-color: # faaaa4; цвет границы: # f44336; }

Чтобы создать окно сообщения об ошибке, нам нужно добавить имена классов msg и msg-error к атрибуту class элемента:

<p class = "msg msg-error"> Произошла ошибка. </ p>

Давайте сопоставим это с атомарной системой, где каждое объявление становится своим собственным классом:

.bg-a {background-color: # a6d5fa; } .bg-b {background-color: #aedbaf; } .bg-c {background-color: # ffe8a5; } .bg-d {background-color: # faaaa4; } .bc-a {border-color: # 2196f3; } .bc-b {border-color: # 4caf50; } .bc-c {border-color: # ffc107; } .bc-d {border-color: # f44336; } .br-1x {border-radius: 10px; } .bw-2x {border-width: 2px; } .bss {border-style: solid; } .sans {font-style: sans-serif; } .p-1x {padding: 10px; }

Это намного больше CSS. Давайте теперь воссоздадим наш компонент сообщения об ошибке. Используя атомарный CSS, наша разметка становится:

<p class = "bw-2 bss p-1x sans br-1x bg-d bc-d"> Произошла ошибка. </ Р>

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

<p class = "bw-2 bss p-1x sans br-1x bg-c bc-c"> Предупреждение. Цена этого элемента изменилась. </ Р>

Два имени классов изменились: bg-d и bc-d были заменены на bg-c и bc-c. Мы повторно использовали пять наборов правил. Теперь давайте создадим кнопку:

<button type = "button" class = "p-1x sans bg-a br-1x"> Сохранить </ button>

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

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

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

Тем не менее, Atomic CSS не без противоречий.

Дело против атомного CSS

Атомный CSS противоречит практически всему, чему нас научили при написании CSS. Это почти так же неправильно, как повсеместно придерживаться атрибутов стиля. Действительно, одна из основных критических замечаний в методологии Atomic CSS заключается в том, что она стирает грань между контентом и представлением. Если class = "fl m-1x" плавает элемент влево и добавляет десятипиксельное поле, что нам делать, если мы больше не хотим, чтобы этот элемент плавал влево?

Конечно, один из ответов - удалить класс fl из нашего элемента. Но теперь мы меняем HTML. Вся причина использования CSS состоит в том, что разметка не зависит от представления и наоборот. (Мы также можем решить эту проблему, удалив правило .fl {float: left;} из нашей таблицы стилей, хотя это повлияет на каждый элемент с именем класса fl.) Тем не менее, обновление HTML может быть небольшой платой за триммер CSS.

В оригинальном посте Кобленца он использовал имена классов, такие как .M-10 для поля: 10px и .P-10 для отступа: 10px. Проблема с таким соглашением об именах должна быть очевидной. Изменение с полем в пять или 20 пикселей означает, что нам нужно обновить наш CSS и наш HTML, или мы рискуем получить имена классов, которые не могут точно описать их эффект.

Использование имен классов, таких как p-1x, как сделано в этом разделе, решает эту проблему. 1x часть имени класса указывает соотношение, а не определенное количество пикселей. Если базовый отступ составляет пять пикселей (то есть .p-1x {padding: 5px;}), тогда .p-2x установит десять пикселей заполнения. Да, это менее наглядно описывает то, что делает имя класса, но это также означает, что мы можем изменить наш CSS без обновления нашего HTML и без создания вводящего в заблуждение имени класса.

Атомная архитектура CSS не мешает нам использовать имена классов, которые описывают содержимое нашей разметки . Вы все еще можете добавить .button-close или .accordion-trigger к вашему коду. Такие имена классов на самом деле предпочтительнее для манипуляций с JavaScript и DOM.

БЭМ против атомного CSS

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

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

Знай, когда идти своим путем

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

Но что происходит, когда мы создаем компонент с предупреждением?
Если class = "fl m-1x" плавает элемент влево и добавляет десятипиксельное поле, что нам делать, если мы больше не хотим, чтобы этот элемент плавал влево?