Atomic BEM CSS улучшенный синтаксис для работы с именами классов


Содержание материала:

One more step

Please complete the security check to access codepen.io

Why do I have to complete a CAPTCHA?

Completing the CAPTCHA proves you are a human and gives you temporary access to the web property.

What can I do to prevent this in the future?

If you are on a personal connection, like at home, you can run an anti-virus scan on your device to make sure it is not infected with malware.

If you are at an office or shared network, you can ask the network administrator to run a scan across the network looking for misconfigured or infected devices.

Another way to prevent getting this page in the future is to use Privacy Pass. You may need to download version 2.0 now from the Chrome Web Store.

Cloudflare Ray ID: 53224a6b989c8fd3 • Your IP : 188.64.174.135 • Performance & security by Cloudflare

Правильный синтаксис списка аргументов для модулей className и css с использованием BEM

Я использую React и очень простые настройки CSS-модулей с помощью webpack. Также используется BEM для имен классов.

Classnames с тире недействительны, если только в строковой форме, и я еще не нашел строчную версию, которая неоднократно ссылается на оператор импорта css для каждой записи класса.

Оба они не идеальны, и я хотел бы избежать использования библиотеки.

Они не работают

Вы можете использовать шаблонные литералы:

хотя я советую использовать классNames, так как это действительно полезно для добавления условных имен классов. Вы также можете использовать привязанный подход

Синтаксис CSS BEM без имени класса элемента

Я должен создать основной компонент заголовка, ниже моя разметка вместе с классами CSS. Я придерживаюсь соглашения об именах БЭМ для имени класса.

У меня элемент h1 состоит из двух пролетов. Один span для текста основного заголовка и второй span для текста подзаголовка. Основным и вспомогательным являются варианты моего заголовка.

Я не указал класс Element (который может быть heading-primary__text ), и я непосредственно прикрепил классы модификаторов к элементам span .

Является ли это правильным способом следовать методологии БЭМ без указания классов элементов и присоединения классов модификаторов блока к элементам ( span )? Потому что мне не нужны элементы классов.

Введение в CCSS (Компонентный CSS)

CCSS или компонентный CSS , это архитектура, которая упрощает составление CSS для крупных веб-приложений.

Большие веб-приложения, как правило, содержат много CSS файлов, над которыми работают разные разработчики.

С появлением такого большого количества фреймворков, руководств, инструментов и методологий ( OOCSS, SMACSS, BEM и т.д.), разработчики нуждаются в CSS архитектуре, которая обеспечит простое сопровождение, управление и масштабирование проектов.

Как инженер интерфейсов, я считаю, что веб-разработка на основе компонентов, это именно то, что нужно. Веб-компоненты представляют собой набор стандартов, которые работают через W3C . Они позволяют нам обернуть разметку и стили в многократно используемые элементы HTML , действительно инкапсулированные.

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

Давайте рассмотрим, что такое CCSS и как вы можете использовать его в настройке архитектуры CSS для сложного веб-приложения.

Элементы CCSS

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

SMACSS

SMACSS, был создан Джонатаном Снуком , и расшифровывается, как Scalable and Modular Architecture for CSS ( Масштабируемая и модулируемая архитектура для CSS ). Это, скорее, руководство по стилям, чем фреймворк. Для получения более детальной информации о том, как он используется в структуре CCSS , прочитайте статью SMACSS .

BEM был создан разработчиками Yandex , расшифровывается, как “ Block ”, “ Element ”, “ Modifier ” (« Блок «, « Элемент «, « Модификатор «). Эта методология предлагает новый подход при разработке веб-интерфейсов. Более подробную информацию по BEM вы можете найти в отличной статье Гарри Робертса .

Sass — это CSS с суперсилами. Я очень рекомендую именно его, но вы можете использовать также Less . Дополнительную информацию вы можете найти в документации Sass .

Compass

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

Примеси Compass практически всегда должны использоваться, когда нам нужны префиксы. Опять же, его применение весьма желательно, или по своему усмотрению вы можете использовать Bourbon .

Принципы CCSS

Теперь давайте рассмотрим основные принципы CCSS .

Компонентная основа

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

При необходимости нужно использовать дополнительные элементы HTML , чтобы сделать возможным многократное использование компонента.

Модульность и изолированность

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

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

Возможность компоновки

При составлении CSS должно уменьшаться количество времени, необходимое для написания CSS , и соответственно нужно больше времени на изменение HTML-классов элементов, модифицируя их или добавляя новые стили.

Для всех разработчиков гораздо проще составлять CSS -код, похожий на блоки конструктора « Лего », чем участвовать в CSS войне. Классы CSS являются строительными блоками, которые используются для составления стилей.

Предсказуемость

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

Документирование

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

Структура каталогов

Ниже для облегчения восприятия приводится пример структуры папок. Я также разместил пример настройки CCSS в хранилище на GitHub :

Нужно только отредактировать / составить файлы в папке scss/ дерева папок , приведенного выше. Это позволяет легко обновлять внешние библиотеки, расположенные в папке ext/ .

Многие приложения поддерживаются внешними CSS -фреймворками, такими как Bootstrap или Foundation , поэтому я добавил их в этом примере в папку ext/ . Хотя конечно здорово, если все CSS -коды пишутся с нуля; тем не менее, вы можете использовать описанный выше метод.

Папка components/ отлично подходит для применения AngularJS , но ее можно настроить под другие фреймворки или приложения. Более подробно я расскажу об этом в разделе « Архитектура ».

На странице HTML , включающей в себя все файлы .css из папки style/ , содержатся все скомпилированные CSS-коды ( из Grunt, Compass и т.д .). Никогда не изменяйте их.

Конвенция имен — упрощенный BEM

  • u-className — глобальные базовые классы / классы утилит;
  • img-className — глобальные классы изображений;
  • animate-className — глобальные классы анимации;
  • ComponentName — стандартные компоненты (B);
  • ComponentName-elementName — элементы компонента (E);
  • ComponentName—modifierName — модификатор компонента (М).

Обратите внимание на название стиля компонентов UpperCamelCase , это основной элемент; это означает, что он является верхним элементом компонента. Имена элементов и модификаторов — elementName и modifierName , соответственно. Не используйте дефис (-), чтобы разделять имена компонентов, так как он означает начало элемента / имени элементов.

Архитектура и дизайн

Давайте рассмотрим архитектуру, построенную согласно принципам CCSS .

Grunt

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

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

Организация файлов

Посмотрите еще раз на структуру папок, которая является производной от SMACSS . Обратите внимание на папку ext/ , которая содержит все внешние фреймворки ( такие как Bootstrap ). Для более простого внесения изменений изменения и расширения должны вноситься не в нее, а в папку base/ .

base/ — это место, где хранятся глобальные базовые стили, используемые приложением в целом.
_base.scss — базовые стили только для селекторов элементов. Они являются своего рода « CSS-переключателями «.
_base-classes.scss — все классы утилит, используемые по всему приложению в разных представлениях, компонентах и на страницах. Используется префикс имени класса u- .
images.scss используется в качестве источника компиляции SCSS . Должен определять и встраивать все изображения сайта, как Data URI . /app/styles/images.css генерируется из этого файла.
_animate.scss содержит все классы анимации всего приложения.
_bootstrap-overrides.scss содержит только файлы, измененные фреймворком. Иногда уровень, назначенный селекторам фреймворка, настолько высок, что их переопределение требует дополнительных селекторов. Изменение на глобальном уровне не может быть осуществлено в контексте компонента SCSS . Вместо этого все глобальные изменения собираются здесь.

Компоненты

Любой блок многоразово используемого CSS -кода, не упомянутого выше, считается « компонентом «. Мы используем AngularJS , поэтому я разделяю их на три основные категории: представления / страницы, директивы и стандарты; следовательно, структура этих папок опирается на SMACSS .

В примере настроек, размещенном на GitHub , я, чтобы было понятнее, создал отдельные папки.

Если ваше приложение невелико, вы можете собрать их все в одну папку. Все компоненты, созданные в соответствии с модифицированной конвенцией имен BEM , используются в сочетании с CamelCase .

Это дало мне огромный плюс, так как стимулировало остальных членов команды следовать синтаксису BEM . Это также позволило избежать путаницы при отходе от использования типичного стиля BEM с его символами -, — и __, которые генерируют такие имена классов, как module-name__child-name—modifier-name !

Также важно, что порядок определения классов CSS в компоненте отражает представление HTML . Это облегчает сканирование, назначение стилей, редактирование и применение классов.

Наконец, хорошо иметь для веб-приложения обширное руководство по стилям и следовать гайдлайнам по CSS и Sass ( например, избавиться от необходимости использования @extend ).

Пример CCSS

Смотрите код примера настроек CSS .

Вот пример компонента на Sass :

Это код компилируется в следующий CSS :

И ваш HTML -код может выглядеть приблизительно следующим образом:

Вы можете задействовать упрощенную BEM-примесь , которая для достижения этой цели использует эталонный селектор, и является более простой, чем @at-root .

В Sass 3.3+ работать с BEM стало намного проще, что дает нам возможность поддерживать и сопровождать код, который легко понять.

Ваше участие

Ваше участие в развитии материалов, размещенных на GitHub , в виде просьб добавить больше примеров, разъяснений и т.д., будет очень полезным.

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

Данная публикация представляет собой перевод статьи « Introducing CCSS (Component CSS) » , подготовленной дружной командой проекта Интернет-технологии.ру

Методология

Технологии

Библиотеки

Соглашение по именованию

Имя БЭМ-сущности уникально. Во всех технологиях (CSS, JavaScript, HTML) одна и та же БЭМ-сущность всегда называется одинаково. Основная идея соглашения по именованию — вложить смысл в имена и сделать их максимально информативными для разработчика.

Можно сравнить одно и тоже имя CSS-селектора, написанное разными способами:

Чтобы понять смысл первого имени, нужно вчитаться в каждое слово. В последних двух примерах имя явно разделяется на логические части. Но ни одно из имен пока не помогает точно определить, что menu — это блок, item — элемент, а visible — модификатор. Чтобы имена сущностей были однозначными и понятными, в БЭМ были разработаны правила формирования имен БЭМ-сущностей.

Правила формирования имен


Имена записываются латиницей в нижнем регистре.

Для разделения слов в именах используется дефис ( — ).

Имя блока задает пространство имен для его элементов и модификаторов.

Имя элемента отделяется от имени блока двумя подчеркиваниями ( __ ).

Имя модификатора отделяется от имени блока или элемента одним подчеркиванием ( _ ).

Значение модификатора отделяется от имени модификатора одним подчеркиванием ( _ ).

Значение булевых модификаторов в имени не указывается.

Важно! В методологии БЭМ не существует элементов элементов. Правила именования запрещают создавать элементы элементов, но в DOM-дереве элементы можно вкладывать друг в друга.

Примеры

В HTML БЭМ-сущности представлены атрибутом class . В БЭМ во всех технологиях происходит обращение к классу:

Примеры правил формирования имен приведены на CSS.

Имя блока

Имя элемента

Важно! Имена одинаковых элементов одного и того же блока совпадают. Например, все пункты в блоке меню называются menu__item .

Имя модификатора блока

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

Альтернативные схемы именования

Описанные выше правила формирования имен — это классическая схема именования БЭМ-сущностей. Все инструменты БЭМ по умолчанию настроены на классическую схему.

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

Стиль Two Dashes

Имена записываются латиницей в нижнем регистре.

Для разделения слов в именах БЭМ-сущностей используется дефис ( — ).

Имя элемента отделяется от имени блока двумя подчеркиваниями ( __ ).

Булевые модификаторы отделяются от имения блока или элемента двумя дефисами ( — ).

Значение модификатора отделяется от его имени двумя дефисами ( — ).

Важно! Двойной дефис внутри комментария ( — ) может вызвать ошибки при валидации HTML-документа.

Стиль CamelCase

Имена записываются латиницей.

Каждое слово внутри имени пишется с заглавной буквы.

Разделители элементов и модификаторов совпадают с классической схемой.

Стиль React

Имена записываются латиницей.

Имена блоков и элементов пишутся с заглавной буквы. Имена модификаторов — со строчной.

Каждое слово внутри имени пишется с заглавной буквы.

Имя элемента отделяется от имени блока одним дефисом ( — ).

Разделители имени и значения модификаторов совпадают с классической схемой.

Стиль No-namespace

Имена записываются латиницей.

Имя блока или элемента перед модификатором не указывается.

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

Ваша схема именования

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

15 инструментов для аудита и оптимизации кода CSS

Созданный сайт будет постоянно расширяться, и однажды вы осознаете, насколько трудно разобраться в его CSS .

Если вы уже столкнулись с подобной проблемой, то пришло время провести аудит вашего CSS -кода и оптимизировать его. Мы отобрали 15 инструментов, которые помогут вам сделать это. Некоторые из них помогут уменьшить размер файла с CSS , другие поспособствуют повышению производительности страниц.

1. Type-o-Matic

Type-o-matic представляет собой Firebug -плагин, который умеет анализировать шрифты, использованные на страницах сайта. Этот плагин выводит отчет в виде таблицы с информацией о свойствах используемых шрифтов ( семейство, размер, цвет и другое ).

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

2. CSSCSS

Инструмент анализирует ваши CSS -файлы на наличие дублей. Это позволит уменьшить размер CSS и гораздо удобнее работать с ними в дальнейшем. Инструмент очень прост в установке – он реализован в виде пакета расширения для Ruby , и запускается из командной строки.

3. CSS Lint

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

Топ-пост этого месяца:  Как установить PHP

4. CSS Colorguard

Зачастую попадаются клиенты, желающие использовать такие цвета, о существовании которых вы даже не подозревали. CSS Colorguard поможет составить необходимые цветовые схемы, и предупредит в том случае, если вы используете два одинаковых цвета.

5. CSS Dig

CSS Dig — это скрипт, написанный на Python , который запускается локально, и позволяет проанализировать свойства и значения CSS практически любого сайта, независимо от того, располагаются ли стили в отдельном файле или в коде страницы. Инструмент также помогает изменять, стандартизировать и оптимизировать CSS -код.

6. Dust Me

Dust-Me – плагин для Firefox и Opera , который выводит неиспользуемые селекторы из таблицы стилей. Инструмент берет весь CSS вашего сайта, и показывает, какие именно селекторы используются, а какие лишние.

7. Devilo.us

Devilo.us – продвинутый движок для сжатия и оптимизации CSS -кода, который теперь поддерживает CSS3 .

8. PurifyCSS

Инструмент помогает избавиться от неиспользуемых CSS -стилей на страницах сайта или в веб-приложениях. Способен определять даже динамически загружаемые CSS -селекторы в javascript-коде, и существенно сжимать размер файлов стилей.

9. Atomic CSS

Atomic CSS поможет уменьшить CSS -файлы. Он позволяет оптимизировать скорость загрузки страниц, исключает зависимости, а также умеет многое другое.

10. Clean CSS

CleanCSS представляет собой многофункциональный CSS -оптимизатор. Инструмент берет ваш CSS -код и делает его чище и меньше в объеме. Вы можете оптимизировать код, написанный на разных языках: javascript , json , python , html и т. д.

11. PubCSS

Инструмент облегчает форматирование CSS -кода страниц академических изданий. Это библиотека CSS -стилей для форматирования документов под печать и публикацию в интернете.

12. CSSO

CSSO (CSS Optimizer) ¬– это инструмент, который производит структурную оптимизацию ваших CSS -файлов.

13. Helium

Helium – это инструмент для выявления неиспользуемых CSS -свойств на всех страницах сайта. Он основан на javascript и работает прямо в браузере. Helium принимает список URL -адресов разделов сайта, а затем анализирует каждую страницу для последующего составления списка всех стилей. После чего выявляет не использующиеся свойства CSS .

14. Strip Comments

Strip CSS Comments значительно облегчает следующие задачи: удаление комментариев из CSS -файлов, уменьшение размеров файлов. Он также доступен в виде плагина для gulp/grunt/broccoli .

15. CSS Shrinks

Инструмент позволяет без труда оптимизировать CSS -файлы, сохраняя последовательность и формат разметки. В нем есть несколько средств, которые позволяют удалять в документе пробелы и комментарии.

Возможно, у вас на примете есть еще какие-нибудь полезные CSS -инструменты? Пожалуйста, поделитесь ими в комментариях!

Данная публикация представляет собой перевод статьи « 15 CSS Tools to Audit and Optimize Your CSS Code » , подготовленной дружной командой проекта Интернет-технологии.ру

Развёрнутое руководство по Sass/SCSS

Современный CSS — мощь, а в комбинации с препроцессорами — вообще боевая машина для оформления контента на страницах. В статье приведено развёрнутое руководство по Sass/SCSS с примерами. После прочтения узнаете, как использовать миксины, переменные и директивы для ещё большего контроля над стилями.

Примечание Весь код Sass/SCSS компилируется в CSS, чтобы браузеры могли его понимать и корректно отображать. В настоящее время браузеры не поддерживают работу с Sass/SCSS или с любым другим препроцессором CSS напрямую, стандартная же спецификация CSS не предоставляет аналогичную функциональность.

Содержание статьи

Зачем использовать Sass/SCSS вместо CSS?

  1. Вложенность — SCSS позволяет вкладывать правила CSS друг в друга. Вложенные правила применяются только для элементов, соответствующих внешним селекторам (а если речь идёт о Sass, то там и без скобок всё красиво и интуитивно понятно).
  2. Переменные — в стандартном CSS тоже есть понятие переменных, но в Sass с ними можно работать немного по-другому. Например, повторять их через директиву @for . Или генерировать свойства динамически. Подробнее можете изучить на русскоязычном сайте проекта.
  3. Улучшенные математические операции— можно складывать, вычитать, умножать и делить значения CSS. В отличие от стандартного CSS, Sass/SCSS позволяют обойтись без calc() .
  4. Тригонометрия — SCSS позволяет писать собственные (синусоидальные и косинусоидальные) функции, используя только синтаксис Sass/SCSS, подобно тому, как это можно делать в других языках вроде JavaScript.
  5. Директивы @for , @while и выражение @if-else — можно писать CSS-код, используя знакомые элементы из других языков. Но не обольщайтесь — в итоге на выходе будет обычный CSS.
  6. Миксины (примеси) — можно один раз создать набор CSS-свойств и работать с ними повторно или смешивать с другими значениями. Миксины можно использовать для создания отдельных тем одного макета. Примеси также могут содержать целые CSS-правила или что-либо другое, разрешённое в Sass-документе. Они даже могут принимать аргументы, что позволяет создавать большое разнообразие стилей при помощи небольшого количества миксинов.
  7. Функции можно создавать определения CSS в виде функций для многократного использования.

Препроцессор Sass

Sass не динамичен. У вас не получится генерировать и/или анимировать CSS-свойства и значения в реальном времени. Но можно их создавать более эффективным способом и позволить стандартным свойствам (вроде анимации на CSS) заимствовать их оттуда.

Синтаксис

SCSS особо не добавляет никаких новых возможностей CSS, кроме нового синтаксиса, часто сокращающего время написания кода.

Пререквизиты

Существует 5 CSS-препроцессоров: Sass, SCSS, Less, Stylus и PostCSS.

Эта статья по большей части охватывает SCSS, который похож на Sass. Детальнее об этих препроцессорах можете прочитать на Stack Overflow (оригинал) или на qaru (перевод на русский).

SASS — (.sass) Syntactically Awesome Style Sheets.

«КРОК», Москва, Троицк, Санкт-Петербург, Нижний Новгород, Самара, Иркутск, Пермь, Краснодар, Воронеж, Челябинск, от 120 000 до 240 000 ₽

SCSS — (.scss) Sassy Cascading Style Sheets.


Расширения .sass и .scss похожи, но всё-таки не одинаковы. Для фанатов командной строки приводим способ конвертации:

Sass — первая спецификация для SCSS с расширением файла .sass . Её разработка началась ещё в 2006 году, но позже был разработан альтернативный синтаксис с расширением .scss .

Обратите внимание Другие препроцессоры функциональностью похожи на SCSS, но синтаксис может отличаться. А ещё, всё то, что работает в CSS, будет также прекрасно воспроизводиться и в Sass, и в SCSS.

Переменные

Sass/SCSS позволяет работать с переменными. В CSS они обозначаются двойным тире ( — ), а в препроцессорах знаком доллара ( $ ).

Вы можете присваивать значение по умолчанию переменным, у которых ещё нет значения, добавив метку !default в конце значения. В таком случае, если переменной уже было присвоено значение, оно не изменится; если же переменная пуста, ей будет присвоено новое указанное значение.

Переменные в Sass могут быть присвоены любому свойству.

Вложенные правила

Стандартные вложенные CSS-элементы с использованием пробела:

Те же вложенные элементы с помощью SCSS:

Как видно, синтаксис выглядит более чистым и менее повторяющимся.

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

За кулисами препроцессор всё ещё компилирует его в стандартный код CSS (показано выше), чтобы он мог быть отображён в браузере. Мы лишь изменяем способ написания CSS.

Амперсанд

В SCSS используется директива & .

С помощью символа & вы можете явно указать, где должен быть вставлен родительский селектор.

Результат компиляции Sass (из предыдущего примера) в CSS ниже.

В итоге амперсанд был компилирован в название родительского элемента a ( a:hover ).

Миксины (они же примеси)

Миксины объявляются директивой @mixin . После неё должно стоять имя миксина и, опционально, его параметры, а также блок, содержащий тело миксина. Например, можно определить миксин flexible() , который далее будет включён, например, в класс .centered-elements следующим образом:

Теперь каждый раз после применения класса .centered-elements к HTML-элементу, последний будет преобразован во Flexbox.

Миксины могут также содержать селекторы, в том числе со свойствами. А селекторы могут содержать ссылки на родительский элемент через амперсанд ( & ), вы ведь помните про него?

Пример работы с несколькими браузерами

Некоторые вещи в CSS весьма утомительно писать, особенно в CSS3, где плюс ко всему зачастую требуется использовать большое количество вендорных префиксов( -webkit- или -moz- ).

Миксины позволяют создавать группы деклараций CSS, которые вам придётся использовать несколько раз на сайте. Хорошей практикой будет использование миксинов для вендорных префиксов. Пример:

Арифметические операции

Как и в реальной жизни, вы не можете работать с числами, у которых несовместимы типы данных (например, сложение рх и em ).

Сложение и вычитание

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

Умножение

Выполняется точно так же, как в CSS, с помощью calc(a * b) , но без calc и круглых скобок. Кроме того, можно ещё отделять знак умножения пробелами от чисел ( 5*6 == 5 * 6 ).

Исключение Нельзя умножать пиксели между собой. То есть, 10px * 10px != 100px . 10px * 10 == 100px .

Деление

С делением дела обстоят немного сложнее, но разобраться можно, ведь в стандартном CSS косая линия (слэш) зарезервирована для использования краткой формы записи свойств. Пример ниже.

Есть три помощника, которые намекнут на возможность деления:

  1. Значение (или любая его часть) хранится в переменной или возвращается функцией.
  2. Значения заключены в круглые скобки.
  3. Значение используется как часть другого арифметического выражения.

Результат компиляции в CSS:

Остаток

Остаток вычисляет остаток от операции деления. Ниже рассмотрим, как создать «зебру» для HTML-списка.

Создание миксина zebra показано во вставке кода сверху. Директивы @for и @if описаны в секции ниже.

Для создания образца надо написать несколько HTML-элементов.

Результат в браузере:

Зебра успешно сгенерирована миксином zebra

Операторы сравнения

Директива @if принимает выражение SassScript и использует вложенные в неё стили в случае, если выражение возвращает любое значение, кроме false или null .

Ниже показано, как работают директивы @if и @else , вложенные в миксин.

Сравнение в действии. Миксин spacing выберет размеры padding ’а, если тот будет больше, чем margin .

После компиляции в CSS:

Логические операторы

Описание логических операторов

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

Строки

В CSS определено 2 типа строк: с кавычками и без. Sass распознаёт и то, и другое. В итоге вы получите в CSS тот тип строк, который использовали в Sass.

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

Пример ниже демонстрирует, как делать не надо.

Можете складывать строки разных типов, если в них нет пробелов. Пример ниже не будет скомпилирован.

Строки, содержащие пробелы, должны быть отделены кавычками. Решение проблемы:

Пример сложения нескольких строк:

Сложение строк и чисел:

Обратите внимание Свойство content работает только с псевдоселекторами :before и :after . Рекомендуется не использовать content в CSS-документе, а напрямую использовать его между тегами в HTML.

Операторы управления потоками

В SCSS есть функции ( fucntion() ) и директивы ( @directive ). Чуть выше мы уже рассматривали пример функции, когда изучали передачу аргументов внутри миксинов.

Функции обычно заключаются в скобки, следующие сразу за её именем. А директива начинается с символа @ .

Подобно JavaScript, SCSS позволяет работать со стандартным набором операторов управления потоками.

if() — это функция (и иногда основа искусственного интеллекта).

Её использование выглядит довольно примитивным: оператор вернёт одно из двух обозначенных в условии значений.

@if — это директива, использующаяся для разветвления на основе условия.

Ниже показано комбо-разветвление с добавлением директивы @else .

Проверка на наличие родительского элемента

Амперсанд выбирает родительский элемент, если тот существует. В ином случае вернёт null . Поэтому может использоваться совместно с директивой @if .

В следующих примерах рассмотрим создание условных CSS-стилей в зависимости от наличия родительского элемента.

Директива @for

Директива @for выводит набор стилей заданное число раз. Для каждого повторения используется переменная-счётчик для изменения вывода.

Директива @for итерируется 5 раз.

Результат компиляции в CSS:

Директива @each

Директива @each устанавливает $var в каждое из значений списка или словаря и выводит содержащиеся в ней стили, используя соответствующее значение $var .

Результат компиляции в CSS:

Директива @while

Директива @while принимает выражение SassScript и циклично выводит вложенные в неё стили, пока выражение вычисляется как true . Она может быть использована для создания более сложных циклов, чем таких, для которых подходит @for , хотя она бывает необходима довольно редко. Например:

Функции в Sass/SCSS

Используя Sass/SCSS можно использовать функции так же, как и в других языках.

Создадим функцию three-hundred-px() , возвращающую 300px.

После применения класса .name ширина элемента будет равна 300 пикселям.

Результат в браузере:

Функции в Sass могут возвращать любое корректное значение CSS и могут быть назначены любому свойству. Они даже могут быть рассчитаны на основе переданного аргумента.

Тригонометрия

Тригонометрические функции sin() и cos() часто встречаются в виде встроенных классов во многих языках, таких как JavaScript, например.

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

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

Преимущество использования тригонометрии в сочетании с CSS выражается в отсутствии дополнительных HTTP-запросов, как это происходит с gif-изображениями.

Можно писать тригонометрические функции на Sass. Об этом читайте далее.

Написание собственных функций

В тригонометрии многие операции основаны на функциях. Каждая функция строится на основе другой. Например, функция rad() требует использования PI() . Функции cos() и sin() требуют использование rad() .

Написание функций на Sass/SCSS очень похоже на написание функций в других языках.

Использование функции pow() :

Использование функции rad() :

Для вычисления тангенса функцией tan() нужно применить функции sin() и cos() .

Заключение

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

Методология БЭМ в примерах


Приветствую Вас дорогой коллега! Сегодня я хочу рассказать про такую технологию в веб-разработке, как БЭМ. А если точнее то, как называть классы объектам документа при верстке. Помню, когда я начинал и не знал про всякие методики типа БЭМ’а мне сложно было придумывать классы, я постоянно путался, у меня постоянно было пересечение классов, что в итоге сильно тормозило работу.

БЭМ (Блок, Элемент, Модификатор) — это не только простое именование классов, это компонентный подход к работе. Компонентный подход — это когда мы делим разрабатываемый интерфейс на отдельные блоки. При надобности данный блок можем использовать в другой части сайта или приложения без дублирования стилей. Сейчас конечно же мало, что понятно, но мы будем разбирать примеры.

Основу БЭМ методологии составляют 3 составляющие:

Их еще называют БЭМ сущности. Ниже мы разберем каждую сущность по отдельности.

Сразу хочу отметить, что по БЭМ’у написана отличная документация на русском языке, усваивается очень легко и просто. Я лично данную документацию перечитывал несколько раз. В первое время я испытывал сложности, а именно когда создавать блок, когда элемент, а модификаторы и вовсе не использовал или использовал не по методике. Теперь наконец-то встало все на свои места.

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

Блоком в БЭМ называют функционально независимый компонент, который может быть повторно использован на любой странице сайта и в любой части документа. Блок именуется только атрибутом class . Название блока (а именно присваемовый класс) должно характеризовать смысл или предназначение блока (что это — «шапка сайта»: header ; «меню»: menu ; «виджет»: widget и т. д.), а не его состояние (какой, состояние — «красный»: red ; «активный»: active и т. п.).

Вот еще пример блока:

А вот это уже будет неправильно:

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

Вложенность блоков

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

Микс блоков

Блоки можно также и миксовать (перемешивать), т. е. совмещение нескольких сущностей в одном блоке. В основном микс используют для переопределения блока в разных частях сайта. Давайте рассмотрим пример.

В данном примере мы блоку logo задали дополнительный класс header__logo , тем самым переопределяя блок logo в шапке сайта header (к примеру, в шапке сайта логотип можно уменьшить до определенных размеров, оставляя все остальное как есть).

Элемент

Элемент — это составляющая блока, которая не может быть использована в отрыве от него. Именование элемента выглядит следующим образом: имя-блока__имя-элемента . То есть название элемента отделяется от имени блока двойным нижним подчеркиванием (__). Также, как и для блока название элемента нужно задавать правильно: «что это?» — «пункт»: item, «текст»: text , т. е. характеризует смысл, а не состояние объекта: «красный»: red, «большой»: big . Думаю, здесь все понятно. Теперь давайте рассмотрим небольшой пример.

Как уже было отмечено, элементы не могут быть сами по себе вне блока. То есть в примере ниже будет неправильно.

Элементы могут быть вложены один в другой. Структура DOM-дерева будет примерно следующей:

Топ-пост этого месяца:  Многоуровневый список в html как создать и стилизовать

Вообще такой подход именования классов задает пространство имен элементам, но в тоже время они зависят от блока. Правила в файле стилей будет представлен плоским списком и будет удобочитаем.

Css

Sass

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

Хочу отметить, что элемент не обязателен для блока. То есть блок может быть и без элементов, а элемент, как вы уже знаете, без блока быть не может.

Когда создавать блок, а когда элемент?

Хороший вопрос, сам им когда-то задавался. Но практика мне подсказала, что создавать блок нужно, если он может быть использован повторно в другом месте. Например, у нас на сайте есть формы. Сам блок формы дизайнер нарисовал в едином стиле, но отличаются только незначительно в разных частях страницы. Форма может быть в модальном окне, может быть встроена прямо в тело статьи, может быть блоком обратной связи и т.д. Таким образом мы создаем единый блок, который может использоваться несколько раз.

Элемент

Создавайте элемент тогда, когда элемент не может существовать без родительской сущности сам по себе. В примере с формой элемент input не может быть вне блока формы, поэтому обязательно помещаем его в блок .form

Модификатор

Модификатор — это БЭМ сущность, которая определяет вид, состояние или поведение блока или элемента. Например:

  • Внешний вид: «какой размер?», «какая тема?», «какой цвет?». Размер — size_m . Тема — theme_dark . Цвет — color_blue ;
  • Состояние — active , disabled , focused .

Модификатор отделяется от названия блока или элемента одинарным нижним подчеркиванием (_). Структура имени модификатора будет следующим:

  • Для блока: имя-блока_модификатор
  • Для элемента: имя-блока__имя-элемента_модификатор

Некоторые разработчики для отделения имени модификатора используют не одинарное нижнее подчеркивание (_), а двойной дефис (—). Я лично использую нижнее подчеркивание. Вы можете использовать то, что вам удобно, но в официальной документации используется нижнее подчеркивание.

Типы модификаторов

Модификаторы могут подразделять на типы: 1. ключ-значение; 2. булево значение.

Ключ-значение

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

  • Для блока: имя-блока_модификатор_значение
  • Для элемента: имя-блока__имя-элемента_модификатор_значение

Значение модификатора от имени отделяется (как и само имя модификатора) одинарным нижним подчеркиванием (_).

Пример

Булевый

Данный модификатор используют только тогда, когда требуется само наличие модификатора, а не его значение. Например, «активно»: active .

Пример

Считается, что при наличии булевого модификатора его значение равняется true .

Что еще предлагает технология БЭМ?

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

Файловая структура проекта

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

  • одному блоку соответствует одна директория;
  • имя блока и имя директории совпадают, например, блок header — директория header/ или блок меню — директория menu/ ;
  • имена директорий элементов начинаются с двойного нижнего подчеркивания (__), например, header/__logo/ или header/__form ;
  • имена директорий модификаторов начинаются с одинарного нижнего подчеркивания (_), например, header/__form_bg ;
  • реализация элементов и модификаторов происходит в отдельных файлах и называются примерно так: form__input.js , form_bg_blue.sass .

Пример

Для примера возьмем блок с формой, структура папок и файлов будет следующая:

Лично мне такой подход к разработке очень нравится. В дальнейшем хочу перейти именно на подобную структуру файлов. Естественно все файлы css и js на выходе будут объединены в общие файлы. Делается это с помощью сборщиков, например таких, как Webpack, Gulp, GruntJs и др.

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

На этом пожалуй и завершу. Задавайте вопросы в комментариях, если таковы имеются. Чем смогу — помогу. Всем пока и до встречи в других моих постах!

Заур Магомедов

Верстальщик с большим опытом работы. Занимаюсь созданием сайтов с 2009 года. Постоянно обучаюсь и совершенствую свои навыки. Веду свои проекты, в том числе и данный блог.

ABEM. A more useful adaptation of BEM.

Easily manage projects with monday.com

BEM (Block Element Modifier) is a popular CSS class naming convention that makes CSS easier to maintain. This article assumes that you are already familiar with the naming convention. If not you can learn more about it at getbem.com to catch up on the basics.

The standard syntax for BEM is:

I’m personally a massive fan of the methodology behind the naming convention. Separating your styles into small components is far easier to maintain than having a sea of high specificity spread all throughout your stylesheet. However, there are a few problems I have with the syntax that can cause issues in production as well as cause confusion for developers. I prefer to use a slightly tweaked version of the syntax instead. I call it ABEM (Atomic Block Element Modifier):

An Atomic Design Prefix

The a/m/o is an Atomic Design prefix. Not to be confused with Atomic CSS which is a completely different thing. Atomic design is a methodology for organizing your components that maximizes the ability to reuse code. It splits your components into three folders: atoms, molecules, and organisms. Atoms are super simple components that generally consist of just a single element (e.g. a button component). Molecules are small groups of elements and/or components (e.g. a single form field showing a label and an input field). Organisms are large complex components made up of many molecule and atom components (e.g. a full registration form).

The difficulty of using atomic design with classic BEM is that there is no indicator saying what type of component a block is. This can make it difficult to know where the code for that component is since you may have to search in 3 separate folders in order to find it. Adding the atomic prefix to the start makes it immediately obvious what folder the component is stored in.

camelCase

It allows for custom grouping

Classic BEM separates each individual word within a section with a single dash. Notice that the atomic prefix in the example above is also separated from the rest of the class name by a dash. Take a look at what happens now when you add an atomic prefix to BEM classic vs camelCase:

At a glance, the component name when reading the classic method looks like it’s called «o subscribe form». The significance of the «o» is completely lost. When you apply the «o-» to the camelCase version though, it is clear that it was intentionally written to be a separate piece of information to the component name.

Now you could apply the atomic prefix to classic BEM by capitalizing the «o» like this:

That would solve the issue of the «o» getting lost amongst the rest of the class name however it doesn’t solve the core underlying issue in the classic BEM syntax. By separating the words with dashes, the dash character is no longer available for you to use as a grouping mechanism. By using camelCase, it frees you up to use the dash character for additional grouping, even if that grouping is just adding a number to the end of a class name.

Your mind will process the groupings faster

camelCase also has the added benefit of making the grouping of the class names easier to mentally process. With camelCase, every gap you see in the class name represents a grouping of some sort. In classic BEM, every gap could be either a grouping or a space between two words in the same group.

Take a look at this silhouette of a classic BEM class (plus atomic prefix) and try to figure out where the prefix, block, element and modifier sections start and end:

Ok, now try this one. It is the exact same class as the one above except this time it is using camelCase to separate each word instead of dashes:

That was much easier wasn’t it? Those silhouettes are essentially what your mind sees when it is scanning through your code. Having all those extra dashes in the class name make the groupings far less clear. As you read through your code, your brain tries to process whether the gaps it encounters are new groupings or just new words. This lack of clarity causes cognitive load to weigh on your mind as you work.

camelCase BEM + atomic prefix

Use multi class selectors (responsibly)

One of the golden rules in BEM is that every selector is only supposed to contain a single class. The idea is that it keeps CSS maintainable by keeping the specificity of selectors low and manageable. On the one hand, I agree that low specificity is preferable over having specificity run rampant. On the other, I strongly disagree that a strict one class per selector rule is the best thing for projects. Using some multi-class selectors in your styles can actually improve maintainability rather than diminish it.

«But it leads to higher specificity! Don’t you know that specificity is inherently evil. «

Uncontrolled specificity that has run wild = bad.

Having some higher specificity declarations doesn’t instantly mean that your CSS is more difficult to maintain. If used in the right way, giving certain rules higher specificity can actually make CSS easier to maintain. The key to writing maintainable CSS with uneven specificity is to add specificity purposefully and not just because a list item happens to be inside a list element.

Besides, don’t we actually want our modifier styles to have greater power over elements than default styles? Bending over backwards to keep modifier styles at the same specificity level as normal styles seems silly to me. When do you actually want your regular default styles to override your specifically designated modifier styles?

Separating the modifier leads to cleaner HTML

This is the biggest change to the syntax that ABEM introduces. Instead of connecting the modifier to the element class, you apply it as a separate class.

One of the things that practically everyone complains about when they first start learning BEM is how ugly it is. It is especially bad when it comes to modifiers. Take a look at this atrocity. It only has three modifiers applied to it and yet it looks like a train wreck:

B__E—M:

Look at all that repetition! That repetition makes it pretty difficult to read what it’s actually trying to do. Now take a look at this ABEM example that has all the same modifiers as the previous example:

A-B__E -M:

Much cleaner isn’t it? It is far easier to see what those modifier classes are trying to say without all that repetitive gunk getting in the way.

When inspecting an element with browser DevTools, you still see the full rule in the styling panel so it retains the connection to the original component in that way:

It’s not much different to the BEM equivalent

Managing state becomes easy

One large advantage that ABEM has over classic BEM is that it becomes immensely easier to manage the state of a component. Let’s use a basic accordion as an example. When a section of this accordion is open, let’s say that we want to apply these changes to the styling:

  • Change the background colour of the section heading
  • Display the content area
  • Make a down arrow point up

We are going to stick to the classic B__E—M syntax for this example and strictly adhere to the one class per css selector rule. This is what we end up with (note, that for the sake of brevity, this accordion is not accessible):

The SCSS looks pretty clean but take a look at all the extra classes that we have to add to the HTML for just a single change in state!


HTML while a segment is closed using BEM:

HTML while a segment is open using BEM:

Now let’s take a look at what happens when we switch over to using this fancy new A-B__E -M method:

A single class now controls the state-specific styling for the entire component now instead of having to apply a separate class to each element individually.

HTML while a segment is open using ABEM:

Also, take a look at how much simpler the javascript has become. I wrote the JavaScript as cleanly as I could and this was the result:

JavaScript when using pure BEM:

JavaScript when using ABEM:

This was just a very simple accordion example. Think about what happens when you extrapolate this out to something like a sticky header that changes when sticky. A sticky header might need to tell 5 different components when the header is sticky. Then in each of those 5 components, 5 elements might need to react to that header being sticky. That’s 25 element.classList.add(«[componentName]__[elementName]—sticky») rules we would need to write in our js to strictly adhere to the BEM naming convention. What makes more sense? 25 unique classes that are added to every element that is affected, or just one -sticky class added to the header that all 5 elements in all 5 components are able to access and read easily?

The BEM «solution» is completely impractical. Applying modifier styling to large complex components ends up turning into a bit of a grey area. A grey area that causes confusion for any developers trying to strictly adhere to the BEM naming convention as closely as possible.

ABEM modifier issues

Separating the modifier isn’t without its flaws. However, there are some simple ways to work around those flaws.

Issue 1: Nesting

So we have our accordion and it’s all working perfectly. Later down the line, the client wants to nest a second accordion inside the first one. So you go ahead and do that. this happens:

Nesting a second accordion inside the first one causes a rather problematic bug. Opening the parent accordion also applies the open state styling to all of the child accordions in that segment.

This is something that you obviously don’t want to happen. There is a good way to avoid this though.

To explain it, let’s play a little game. Assuming that both of these CSS rules are active on the same element, what color do you think that element’s background would be?

If you said green due to the first rule having a higher specificity than the second rule, you would actually be wrong. Its background would be blue.

Fun fact: * is the lowest specificity selector in CSS. It basically means «anything» in CSS. It actually has no specificy, meaning it doesn’t add any specificity to a selector you add it to. That means that even if you used a rule that consisted of a single class and 5 stars ( .element > * > * > * > * > * ) it could still be easily overwritten by just a single class on the next line of CSS!

We can take advantage of this little CSS quirk to create a more targeted approach to the accordion SCSS code. This will allow us to safely nest our accordions.

By using the .-modifierName > * > & pattern, you can target direct descendants that are multiple levels deep without causing your specificity to get out of control.

I only use this direct targeting technique as it becomes necessary though. By default, when I’m writing ABEM, I’ll write it how I did in that original ABEM accordion example. The non-targeted method is generally all that is needed in most cases. The problem with the targeted approach is that adding a single wrapper around something can potentially break the whole system. The non-targeted approach doesn’t suffer from this problem. It is much more lenient and prevents the styles from breaking if you ever need to alter the HTML later down the line.

Issue 2: Naming collisions

An issue that you can run into using the non-targeted modifier technique is naming collisions. Let’s say that you need to create a set of tabs and each tab has an accordion in it. While writing this code, you have made both the accordion and the tabs respond to the -active class. This leads to a name collision. All accordions in the active tab will have their active styles applied. This is because all of the accordions are children of the tab container elements. It is the tab container elements that have the actual -active class applied to them. (Neither the tabs nor the accordion in the following example are accessible for the sake of brevity.)

Топ-пост этого месяца:  Разработка веб-приложения на PHP прием платежей на сайте

Now one way to resolve this conflict would be to simply change the accordion to respond to an -open class instead of an -active class. I would actually recommend that approach. For the sake of an example though, let’s say that isn’t an option. You could use the direct targeting technique mentioned above, but that makes your styles very brittle. Instead what you can do is add the component name to the front of the modifier like this:

The dash at the front of the name still signifies that it is a modifier class. The component name prevents namespace collisions with other components that should not be getting affected. The double dash is mainly just a nod to the classic BEM modifier syntax to double reinforce that it is a modifier class.

Here is the accordion and tabs example again but this time with the namespace fix applied:

I recommend not using this technique by default though mainly for the sake of keeping the HTML clean and also to prevent confusion when multiple components need to share the same modifier.

The majority of the time, a modifier class is being used to signify a change in state like in the accordion example above. When an element changes state, all child elements, no matter what component they belong to, should be able to read that state change and respond to it easily. When a modifier class is intended to affect multiple components at once, confusion can arise around what component that modifier specifically belongs to. In those cases, name-spacing the modifier does more harm than good.

ABEM modifier technique summary

So to make the best use of the ABEM modifier, use .-modifierName & or &.-modifierName syntax by default (depends on what element has the class on it)

Use direct targeting if nesting a component inside itself is causing an issue.

Use the component name in the modifier if you run into shared modifier name collisions. Only do this if you can’t think of a different modifier name that still makes sense.

Context sensitive styles

Another issue with strictly adhering to the BEM one class per selector methodology is that it doesn’t allow you to write context sensitive styles.

Context sensitive styles are basically «if this element is inside this parent, apply these styles to it».

With context sensitive styles, there is a parent component and a child component. The parent component should be the one that applies layout related styles such as margin and position to the child component ( .parent .child < margin: 20px >). The child component should always by default not have any margin around the outside of the component. This allows the child components to be used in more contexts since it is the parent in charge of it’s own layout rather than its children.

Just like with real parenting, the parents are the ones who should be in charge. You shouldn’t let their naughty clueless children call the shots when it comes to the parents layout.

To dig further into this concept, let’s pretend that we are building a fresh new website and right now we are building the subscribe form component for the site.

This is the first time we have had to put a form on this awesome new site that we are building. We want to be like all the cool kids so we used CSS grid to do the layout. We’re smart though. We know that the button styling is going to be used in a lot more places throughout the site. To prepare for this, we separate the subscribe button styles into its own separate component like good little developers.

A while later we start cross-browser testing. We open up IE11 only to see this ugly thing staring us in the face:

IE11 does kind of support CSS grid but it doesn’t support grid-gap or auto placement. After some cathartic swearing and wishing people would update their browsers, you adjust the styles to look more like this:

Now it looks perfect in IE. All is right with the world. What could possibly go wrong?

A couple of hours later you are putting this button component into a different component on the site. This other component also uses css-grid to layout its children.

You write the following code:

You expect to see a layout that looks like this even in IE11:

But instead, because of the grid-column: 3; code you wrote earlier, it ends up looking like this:

Yikes! So what do we do about this grid-column: 3; CSS we wrote earlier? We need to restrict it to the parent component but how should we go about doing that?

Well the classic BEM method of dealing with this is to add a new parent component element class to the button like this:

On the surface this solution looks pretty good:

  • It keeps specificity low
  • The parent component is controlling its own layout
  • The styling isn’t likely to bleed into other components we don’t want it to bleed into

Everything is awesome and all is right with the world… right?

The downside of this approach is mainly due to the fact that we had to add an extra class to the button component. Since the subscribe-form__submit class doesn’t exist in the base button component, it means that we need to add extra logic to whatever we are using as our templating engine for it to receive the correct styles.

I love using Pug to generate my page templates. I’ll show you what I mean using Pug mixins as an example.

First, here is the original IE unfriendly code re-written in mixin format:

Now lets add that IE 11 subscribe-form__submit class to it:

That wasn’t so hard, so what am I complaining about? Well now let’s say that we sometimes want this module to be placed inside a sidebar. When it is, we want the email input and the button to be stacked on top of one another. Remember that in order to strictly adhere to BEM, we are not allowed to use anything higher in specificity than a single class in our styles.

That Pug code isn’t looking so easy now is it? There are a few things contributing to this mess.

  1. Container queries would make this far less of a problem but they don’t exist yet natively in any browser
  2. The problems around the BEM modifier syntax are rearing their ugly heads.

Now lets try doing it again but this time using context sensitive styles:

Look at how much simpler the Pug markup has become. There is no «if this then that» logic to worry about in the pug markup. All of that parental logic is passed off to the css which is much better at understanding what elements are parents of other elements anyway.

You may have noticed that I used a selector that was three classes deep in that last example. It was used to apply 100% width to the button. Yes a three class selector is ok if you can justify it.

I didn’t want 100% width to be applied to the button every time it was:

  • used at all anywhere
  • placed inside the subscribe form
  • placed inside the side-bar

I only wanted 100% width to be applied when it was both inside the subscribe form and inside the sidebar. The best way to handle that was with a three class selector.

Ok, in reality, I would more likely use an ABEM style -verticalStack modifier class on the subscribe-form element to apply the vertical stack styles or maybe even do it through element queries using EQCSS. This would mean that I could apply the vertical stack styles in more situations than just when it’s in the sidebar. For the sake of an example though, I’ve done it as context sensitive styles.

Now that we understand context sensitive styles, let’s go back to that original example I had and use some context sensitive styles to apply that troublesome grid-column: 3 rule:

Context sensitive styles lead to simpler HTML and templating logic whilst still retaining the reusability of child components. BEM’s one class per selector philosophy doesn’t allow for this to happen though.

Since context sensitive styles are primarily concerned with layout, depending on circumstances, you should generally use them whenever you are dealing with these CSS properties:

  • Anything CSS grid related that is applied to the child element ( grid-column , grid-row etc.)
  • Anything flexbox related that is applied to the child element ( flex-grow , flex-shrink , align-self etc.)
  • margin values greater than 0
  • position values other than relative (along with the top , left , bottom , and right properties)
  • transform if it is used for positioning like translateY

You may also want to place these properties into context-sensitive styles but they aren’t as often needed in a context sensitive way.

To be absolutely clear though, context sensitive styles are not nesting for the sake of nesting. You need to think of them as if you were writing an if statement in JavaScript.

So for a CSS rule like this:

You should think of it like you are writing this sort of logic:

Also understand that writing a rule that is three levels deep like this:

Should be thought of like you are writing logic like this:

So by all means, write a css selector that is three levels deep if you really think you need that level of specificity. Please understand the underlying logic of the css that you are writing though. Only use a level of specificity that makes sense for the particular styling that you are trying to achieve.

And again, one more time, just to be super clear, do not nest for the sake of nesting!

Summing Up

The methodology behind the BEM naming convention is something that I wholeheartedly endorse. It allows css to be broken down into small easily manageable components rather than leaving css in an unwieldy mess of high specificity that is difficult to maintain. The official syntax for BEM has a lot to be desired though.

The official BEM syntax:

  • Doesn’t support Atomic Design
  • Is unable to be extended easily
  • Takes longer for your mind to process the grouping of the class names
  • Is horribly incompetent when it comes to managing state on large components
  • Tries to encourage you to use single class selectors when double class selectors lead to easier maintainability
  • Tries to name-space everything even when namespacing causes more problems than it solves.
  • Makes HTML extremly bloated when done properly

My unofficial ABEM approach:

  • Makes working with Atomic Design easier
  • Frees up the dash character as an extra method that can be used for grouping
  • Allows your mind to process the grouping of the class names faster
  • Is excellent at handling state on any sized component no matter how many sub components it has
  • Encourages controlled specificity rather than just outright low specificity to mitigate team confusion and improve site maintainability
  • Avoids namespacing when it isn’t needed
  • Keeps HTML quite clean with minimal extra classes applied to modules while still retaining all of BEM’s advantages

Disclaimer

I didn’t invent the -modifier (single dash before the modifier name) idea. I discovered it in 2020 from reading an article. I can’t remember who originally conceptualised the idea. I’m happy to credit them if anyone knows the article though.

Update: 21 st of January 2020 (comments response)

No one was able to link to the exact article where I learnt about the -modifier syntax. What I can say is that I learnt it from reading an article about BEVM (block__element—variation -modifier).

Here are some other people that came up with the -modifier syntax before me:

BEVM can still work with ABEM if you like that methodology (making it ABEVM). After using the -modifier syntax for a while though I eventually stopped using the &—modifier syntax altogether. I couldn’t really see any benefit in keeping the double dash around when the single dash was easier to use in my CSS and was making my HTML much cleaner.

There were a few people who referenced BEMIT as being quite similar. They’re right, it does share some similarities with BEMIT but it also has some differences.

You could merge ABEM and BEMIT together to an extent. I had people mention that they prefer the explicit «is» of the state based classes in BEMIT (eg. .is-active ). That is perfectly fine, if you want to add the «is» to ABEM I would recommend writing the modifier like this .-is-modifierName . See what I mean by camelCase allowing for custom grouping?

The utilities can be carried across from BEMIT as well pretty easily, it would still be written as .u-utilityName . The «utilities» folder/file should maybe be placed in the same directory as the atoms, molecules and organisms folders. I think that might make it easier to find. The «object» and «component» name spaces in BEMIT wouldn’t carry across. They would be replaced with the Atomic Design name spaces in ABEM.

An interesting discussion in the comments was about using the @extend functionality in Sass. For example using and .subscribe-form__submit < @extend .button; grid-column: 3; >. I think context sensitive styles are the better way to go. I pretty strongly disagreed with that implementation of @extend unless the CMS is forcing you down that path. You can see the full comment and my response here: https://css-tricks.com/abem-useful-adaptation-bem/#comment-1613824.

A thing many people had issue with was that I didn’t go into much depth around what Atomic Design is and how to use it. It was out of scope for this article. If I tried to go in depth on how to categorize components using Atomic Design principles, then it would have easily doubled the length of the article (and this article is already very long as it is). I gave enough of a summary to introduce the concept of Atomic Design and I linked to a resource that goes much more in depth on the topic. That was about as much attention as I wanted to give to explaining Atomic Design.

Since Atomic Design categorization is such a confusing subject, I have plans to write an article that will be all about how to go about categorizing Atomic Design components. I will attempt to create a set of clear guidelines to follow to help figure out what Atomic Design category a particular component belongs to. Don’t expect it any time soon though. It’s going to be a while before it gets published.

Update: 2 nd of April 2020 (Atomic Categorization tool)

So those plans to write an Atomic Design article never came to fruition. I started planning one out, but I began to realize that writing an article to try and explain all the little things that you need to consider when categorizing modules was the wrong way to go about it. A tool that gave you a recommendation at the end would be far more useful.

So I got to work and I am happy to announce the launch of my brand new Atomic Categorizer tool!

It is a simple quiz that gives you points toward each category as you answer the questions. The questions and points might not be 100% perfect but I think it does a pretty good job of categorizing the components most of the time. Give it a try, it’s way more fun than reading another couple thousand words worth of text. ��

Методологии верстки: БЭМ, AMCSS, OOCSS, Atomic CSS, OPOR, MCSS, SMACSS, FUN, DoCSSa (Елизавета Селиванова и Ирина Левина)

Докладчики: Елизавета Селиванова и Ирина Левина

А вы верите в систематизацию, или методологии верстки?

Видео

Слайды

Тезисы

  • Для чего нужны методологии
  • Методологии и их описание
  • Сильные и слабые стороны
  • Как принять эту веру. Практические советы
2 comments on “ Методологии верстки: БЭМ, AMCSS, OOCSS, Atomic CSS, OPOR, MCSS, SMACSS, FUN, DoCSSa (Елизавета Селиванова и Ирина Левина) ”

А вы верите в систематизацию, или методологии верстки?

Верю в методологии если активно дорабатывать их под себя.
Например вот моя доработанная бэм-методолгия. Ведь удобство разработки и поддержки – вещь в значительной степени субъективная.

Я верю в методологии верстки.
Как по мне CSS и HTML также заслуживают своей архитектуры, как все языки программирования. Они не только заслуживают, но должны разрабатываться по какой то методологии чтобы не было плохого кода.
Я использую методологи Atomic CSS и очень ней доволен, к тому же для нее есть замечательные инструменты типа Orna и Atomizer.

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