ABEM. Більш корисна адаптація BEM CSS

17

Від автора: BEM CSS — популярний угода про імена класів CSS, спрощує CSS. У цій статті передбачається, що ви вже знайомі з цією угодою. Якщо ні, більше про це можна знайти на сайті getbem.com, щоб отримати базові знання.

Стандартний синтаксис для BEM:

block-name__element-name—modifier-name

Особисто я великий шанувальник методології угоди про імена. Поділ стилів на невеликі компоненти набагато легше підтримувати, ніж мати море високої специфічності, що поширився по всій таблиці стилів. Однак є кілька нюансів з синтаксисом, які можуть викликати проблеми в процесі виробництва, а також створювати плутанину для розробників. Замість цього я віддаю перевагу використовувати злегка змінену версію синтаксису. Я називаю це ABEM (Atomic Block Element Modifier):

[a/m/o]-blockName__elementName -modifierName

Префікс Atomic Design

A / m / o — префікс Atomic Design. Не слід плутати з Atomic CSS, що зовсім інше. Атомний дизайн — це метод організації компонентів, який максимізує можливість повторного використання коду. Він розбиває компоненти на три папки: атоми, молекули і організми. Атоми — це суперпростые компоненти, які зазвичай складаються з одного елемента (наприклад, компонента button). Молекули являють собою невеликі групи елементів і / або компонентів (наприклад, одне поле форми, показує мітку і поле введення). Організми являють собою великі складні компоненти, що складаються з безлічі компонентів молекул і атомів (наприклад, повна форма реєстрації).

ABEM. Більш корисна адаптація BEM CSS

Складність використання атомного дизайну з класичним BEM полягає у відсутності індикатора, що вказує, який тип компонента є блоком. Це може ускладнити визначення розташування коду для цього компонента, і може знадобитися виконати пошук в трьох окремих папках, щоб знайти. Додавання атомарного префікса на початку відразу робить видимим, в якій папці зберігається компонент.

camelCase

Те, що дозволяє налаштовувати угруповання

Класичний BEM поділяє кожне окреме слово у секції за допомогою тире. Зверніть увагу, що атомний префікс у наведеному вище прикладі також відокремлений тире від іншої частини імені класу. Погляньте на те, що відбувається, коли ви додаєте атомний префікс до BEM classic vs camelCase:

/* classic + atomic prefix */
.o-subscribe-form__field-item {}
/* camelCase + atomic prefix */
.o-subscribeForm__fieldItem {}

З першого погляду ім’я компонента при читанні класичного методу виглядає як «o subscribe form». Значення «о» повністю втрачено. Проте, коли ви застосовуєте «o-» до версії camelCase, стає ясно, що це навмисно було записано як окремий фрагмент інформації для імені компонента.

Тепер ви можете застосувати атомний префікс до класичного BEM, використовуючи «o» наступним чином:

/* classic + capitalized atomic prefix */
.O-subscribe-form__field-item {}

Це дозволило б вирішити проблему «о», загубленої серед решти назви класу, однак не вирішить основної проблеми в класичному синтаксисі BEM. Розділяючи слова тире, тире більше не доступне для використання в якості механізму угруповання. Використання camelCase звільняє вас від використання символу тирі для додаткової угруповання, навіть якщо ця угруповання просто додає номер у кінці імені класу.

Більш швидка обробка угруповань

camelCase володіє додатковою перевагою, завдяки чому легше групувати імена класів. З camelCase кожен пробіл, який є в імені класу, являє собою деяку угруповання. У класичному BEM кожен пробіл може бути або угрупованням, або пропуском між двома словами в одній групі.

Погляньте на малюнок класичного класу BEM (плюс атомний префікс) і спробуйте з’ясувати, де починаються і закінчуються розділи префікса, блоку, елемента і модифікатора:

ABEM. Більш корисна адаптація BEM CSS

А тепер спробуйте інакше. Це той же самий клас, що і вище, за винятком того, що він використовує camelCase для поділу кожного слова замість тире:

ABEM. Більш корисна адаптація BEM CSS

Значно простіше, чи не так? Ці силуети — те, що бачить ваш розум, коли переглядає код. Наявність всіх цих зайвих тире в імені класу робить групи менш зрозумілими. Коли ви читаєте код, ваш мозок намагається обробити, є прогалини, з якими він стикається, новими групами або це просто нові слова. Відсутність ясності призводить до того, що когнітивна навантаження впливає на ваш розум при роботі.

класичний BEM + атомний префікс

ABEM. Більш корисна адаптація BEM CSS

camelCase BEM + атомний префікс

ABEM. Більш корисна адаптація BEM CSS

Використання многоклассового селектора (відповідально)

Одним із золотих правил BEM є те, що кожен селектор повинен містити тільки один клас. Ідея полягає в тому, що він підтримує CSS, зберігаючи специфічність селекторів низькою і керованою. З одного боку, з огляду на рухому динаміку специфічності, я згоден з тим, що низька специфічність краще. З іншого боку, категорично не згоден, що для проектів найкраще підходить один клас за вибір правил. Використання деяких многоклассовых селекторів у ваших стилях може фактично поліпшити поддерживаемость, а не зменшувати її.

«Але це призводить до більш високої специфічності! Хіба ви не знаєте, що специфічність по своїй суті — зло?»

Специфічність! = Погано.

Неконтрольована здичавіла специфічність = bad.

Наявність більш високих специфікацій не означає, що CSS буде складніше підтримувати. При використанні в правильному напрямку, що дає певні можливості управління більш високою специфічністю, можна зробити CSS набагато простіше в обслуговуванні. Ключ до написання підтримуваного CSS з нерівномірною специфікою полягає в тому, щоб цілеспрямовано додавати визначеність, а не тільки тому, що елемент списку знаходиться всередині елемента списку.

Крім того, чи не хочемо ми, щоб наші стилі модифікаторів володіли більшою владою над елементами, ніж стилі за замовчуванням? Лізти геть зі шкіри, щоб зберегти стилі модифікаторів з тим же рівнем специфічності, що і звичайні стилі, мені здається дурним. Коли дійсно потрібно, щоб звичайні стилі за замовчуванням переопределяли спеціально визначені стилі модифікаторів?

Поділ модифікатора призводить до більш чистому HTML

Це найбільша зміна в синтаксисі, який вводить ABEM. Замість того, щоб підключати модифікатор до класу елемента, він застосовується як окремий клас.

Одна з речей, на які практично кожен скаржиться, коли вони вперше починають вивчати BEM, — це потворність. Це особливо погано, коли мова йде про модифікатори. Погляньте на цей злочин. У нього є тільки три модифікатора, і все ж він виглядає як аварія поїзда:

B__E — МУ:

Submit

Подивіться на всі ці повторення! Вони ускладнюють читання того, що він насправді намагається зробити. Тепер розглянемо приклад ABEM, який має всі ті ж модифікатори, що і попередній приклад:

A-B__E -M:

Submit

Набагато чистіше, чи не так? Набагато легше побачити, що намагаються сказати ті класи-модифікатори, не заважаючи цим повторюваним сміттям.

При перевірці елемента з браузером DevTools ви все ще бачите повне правило на панелі стилізації, щоб таким чином зберегти з’єднання з вихідним компонентом:

.a-blockName__elementName.-green { background: green; color: white; }

Це не сильно відрізняється від еквівалента BEM

.block-name__element-name—green { background: green; color: white; }

Управління станом стає простим

Одним великою перевагою ABEM над класичним BEM є те, що стає набагато простіше керувати станом компонента. Давайте використаємо в якості прикладу базовий акордеон. Коли частина цього акордеона буде відкрита, скажімо, що ми хочемо застосувати ці зміни до стилю:

Змінимо кольору фону заголовка розділу

Відобразимо області вмісту

Зосередимо стрілку внизу

Будемо в цьому прикладі дотримуватися класичного синтаксису B__E-M і правила одного класу для CSS-селектора. Це те, чим ми закінчуємо (зверніть увагу, що для стислості цей акордеон недоступний):

SCSS виглядає досить чистим, але погляньте на всі додаткові класи, які ми повинні додати HTML тільки для однієї зміни стану!

HTML, в той час як сегмент закривається з використанням BEM:

Three

Lorem ipsum dolor sit amet…

HTML, в той час як сегмент відкривається з використанням BEM:

One

Lorem ipsum dolor sit amet…

Тепер давайте подивимося, що станеться, коли ми перейдемо до використання цього нового методу A-B__E -M:

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

HTML, коли сегмент відкритий з використанням ABEM:

One

Lorem ipsum dolor sit amet…

Крім того, подивіться, наскільки простіше стало javascript. Я написав JavaScript так, як міг, і це було результатом:

JavaScript при використанні чистого BEM:

class revealer {
constructor(el){
Object.assign(this, {
$wrapper: el,
targets: [‘trigger’, ‘icon’, ‘content’],
isOpen: false,
});
this.gather_elements();
this.$trigger.onclick = ()=> this.toggle();
}
gather_elements(){
const keys = this.targets.map(selector => `$${selector}`);
const elements = this.targets.map(selector => {
return this.$wrapper.querySelector(`.revealer__${selector}`);
});
let elObject = {};
keys.forEach((key, i) => {
elObject[key] = elements;
});
Object.assign(this, elObject);
}
toggle(){
if (this.isOpen) {
this.close();
} else {
this.open();
}
}
open(){
this.targets.forEach(target => {
this[`$${target}`].classList.add(`revealer__${target}—open`);
})
this.isOpen = true;
}
close(){
this.targets.forEach(target => {
this[`$${target}`].classList.remove(`revealer__${target}—open`);
})
this.isOpen = false;
}
}
document.querySelectorAll(‘.revealer’).forEach(el => {
new revealer(el);
})

JavaScript при використанні ABEM:

class revealer {
constructor(el){
Object.assign(this, {
$wrapper: el,
isOpen: false,
});
this.$trigger = this.$wrapper.querySelector(‘.m-revealer__trigger’);
this.$trigger.onclick = ()=> this.toggle();
}
toggle(){
if (this.isOpen) {
this.close();
} else {
this.open();
}
}
open(){
this.$wrapper.classList.add(`-open`);
this.isOpen = true;
}
close(){
this.$wrapper.classList.remove(`-open`);
this.isOpen = false;
}
}
document.querySelectorAll(‘.m-revealer’).forEach(el => {
new revealer(el);
})

Це був просто простий приклад акордеона. Подумайте про те, що відбувається, коли ви экстраполируете його на щось подібне до липкого заголовка, який змінюється, коли він липне. Липкий заголовок може вимагати вказати 5 різних компонентів, потім в кожному з цих 5 компонентів 5 елементів, можливо, зажадають відреагувати на те, що цей заголовок липне. Це 25 element.classList.add(«[componentName]__[elementName]—sticky»)правил, які нам потрібно написати в js, щоб суворо дотримуватися угоди про імена BEM. У чому сенс? 25 унікальних класів, які додаються до кожного порушеного елементу або тільки один sticky — клас, доданий в заголовок, який дозволяє легко і просто прочитати все 5 елементів з усіх 5 компонентів?

«Рішення» BEM абсолютно недоцільно. Застосування стилізації модифікатора до великим складним компонентів закінчується перетворенням в сіру область. Сіра область, яка викликає плутанину у будь-яких розробників, які намагаються суворо дотримуватися угоди про імена BEM.

Проблеми з модифікатором ABEM

Поділ модифікатора не позбавлене недоліків. Однак є кілька простих способів їх обійти.

Проблема 1: Вкладення

Отже, у нас є наш акордеон, і все працює відмінно. Пізніше по лінії клієнт хоче вставити другий акордеон в перший. Отже, ви берете і робите … але відбувається це:

Вкладення другого акордеона всередині першого викликає досить проблематичную помилку. Відкриття батьківського акордеона також застосовує стиль відкритого стану всіх дочірніх акордеонів у цьому сегменті.

Це те, чого ви, очевидно, не хочете. Однак є хороший спосіб уникнути цього.

Щоб пояснити це, давайте трохи пограємо. Припускаючи, що обидва ці правила CSS активні в одному і тому ж елементі, який колір, на вашу думку, буде мати фон елемента?

.-green > * > * > * > * > * > .element { background: green; } .element.-blue { background: blue;
}

Якщо ви сказали, що зелений з-за того, що перше правило має більш високу специфічність, ніж друге правило, ви насправді помиляєтеся. Його фон буде синім.

Кумедний факт: *найнижчий селектор специфічності в CSS. Це в основному означає «що-небудь» в CSS. Насправді він не має ніякої специфіки, тобто він не додає ніякої специфіки до селектору, в який ви додали. Це означає, що навіть якщо ви використовували правило, складається з одного класу 5 зірок ( .element > * > * > * > * > *), його все одно можна було б легко замінити тільки одним класом у наступному рядку CSS!

Ми можемо скористатися цією маленькою примхою CSS, щоб створити більш цілеспрямований підхід до коду SCSS акордеона. Це дозволить нам безпечно вбудовувати наші акордеони.

Використовуючи .-modifierName > * > &шаблон, ви можете націлити прямих нащадків з кількома рівнями глибини, не викликаючи зависання вашої специфіки.

Я використовую цей метод прямого націлювання, оскільки він стає необхідним. За промовчанням, коли я пишу ABEM, я напишу його, як я зробив у цьому оригінальному прикладі акордеона ABEM. У більшості випадків нецільовим методом є все, що необхідно. Проблема з цільовим підходом полягає в тому, що додавання єдиної оболонки навколо чогось потенційно може порушити всю систему. Недоцільний підхід не страждає від цієї проблеми. Це більш поблажливо і не дозволяє стилям руйнуватися, якщо вам раптом коли-небудь знадобиться змінити HTML.

Проблема 2: Найменування колізій

Проблема, з якою ви можете зіткнутися в нецільового використання методу модифікатора — це найменування конфліктів. Припустимо, що вам потрібно створити набір вкладок, і на кожній вкладці є акордеон. При написанні цього коду ви зробили акордеон, а вкладки відповідають active-класу. Це призводить до зіткнення імен. Всі акордеони на активній вкладці будуть застосовані до їх активним стилям. Це пов’язано з тим, що всі акордеони є дочірніми елементами елементів контейнера табуляції. Це елементи контейнера вкладки, які мають дійсний active-клас, що застосовується до них. (Для стислості не доступні ні вкладки, ні акордеон в наступному прикладі).

Як один із способів вирішення конфлікту можна було б просто змінити акордеон для відповіді на open-клас замість active-класу. Я б рекомендував цей підхід. Але припустимо, це не варіант. Тоді можна використовувати метод прямого націлювання, згаданий вище, але це зробить стилі дуже крихкими. Замість цього можна додати ім’я компонента в початок модифікатора наступним чином:

.o-componentName { &__elementName { .-componentName—modifierName & { /* modifier styles go here */ } } }

Риска на початку імені означає, як і раніше, що це клас модифікатора. Ім’я компонента запобігає зіткнення простору імен з іншими компонентами, які не повинні бути порушені. Подвійна тире в основному просто киває класичного синтаксису модифікатора BEM, щоб подвоїти посилення, що це клас модифікатора.

Нижче наведено приклад акордеона і табуляції, але на цей раз з застосуванням виправлення простору імен:

Я не рекомендую використовувати цей метод за замовчуванням, в основному для того, щоб тримати HTML в чистоті, а також для запобігання плутанини, коли кілька компонентів повинні використовувати один і той же модифікатор.

У більшості випадків клас модифікатора використовується для позначення зміни стану, як у наведеному вище прикладі акордеона. Коли елемент змінює стан, всі дочірні елементи, незалежно від того, до якого компоненту вони належать, повинні мати можливість прочитати це зміна стану і швидко відреагувати на нього. Коли клас модифікатора призначений для одночасного впливу на декілька компонентів, може виникнути плутанина навколо того, кому конкретно належить модифікатор. У цих випадках зміна імені модифікатором приносить більше шкоди, ніж користі.

Методика модифікатора АВЕМ

Щоб найкращим чином використовувати модифікатор ABEM, використовуйте синтаксис .-modifierName & або &.-modifierName за замовчуванням (залежить від того, який елемент має клас на ньому)

.o-componentName { &.-modifierName { /* componentName modifier styles go here */ } &__elementName { .-modifierName & { /* elementName modifier styles go here */ } } }

Використовуйте прямий таргетинг, якщо вкладеність компонента всередині себе викликає проблему.

.o-componentName { &__elementName { .-nestedModifierName > * > & { /* modifier styles go here */ } } }

Використовуйте ім’я компонента в модифікаторі, якщо ви зіткнулися з конфліктами спільно використовуваних імен модифікаторів. Тільки робіть це, якщо ви не можете придумати інше ім’я модифікатора, яке все ще має сенс.

.o-componentName { &__elementName { .-componentName—sharedModifierName & { /* modifier styles go here */ } } }

Контекстно-залежні стилі

Ще одна проблема з суворим дотриманням BEM по одному класу за методологією вибору полягає в тому, що вона не дозволяє писати стилі, чутливі до контексту.

Контекстно-залежні стилі в основному це- «якщо даний елемент всередині батьків, застосуйте до нього певні стилі».

З контекстно-залежними стилями існує батьківський компонент і дочірній компонент. Батьківський компонент повинен бути тим, який застосовує стилі, пов’язані з розкладкою, такі як margin і позиція для дочірнього компонента ( .parent .child { margin: 20px }). Дочірній компонент за замовчуванням ніколи не повинен мати поля навколо зовнішньої частини компонента. Це дозволяє використовувати дочірні компоненти у великій кількості контекстів, оскільки він є батьком, відповідальним за його власний макет, а не його дочірні елементи.

Як і у випадку з справжнім вихованням, батьки повинні бути відповідальними. Не можна дозволяти своїм неслухняним неосвіченим дітям командувати, коли мова йде про макеті батьків.

Щоб заглибитися в цю концепцію, давайте удамо, що ми будуємо абсолютно новий веб-сайт, і зараз ми створюємо компонент форми підписки для нього.

Це перший раз, коли нам довелося ставити форму на цьому дивному новому сайті, який ми будуємо. Ми хочемо бути схожими на всіх класних дітей, тому ми використовували сітку CSS для створення макета. Ми розумні, і знаємо, що стилізація кнопок буде використовуватися в багатьох місцях по всій території сайту. Щоб підготуватися до цього, ми поділяємо стилі кнопок підписки на окремі компоненти, як хороші маленькі розробники.

Через деякий час починаємо крос-браузерне тестування. Ми відкриваємо IE11 тільки для того, щоб побачити потворну річ, яка дивиться прямо на нас:

ABEM. Більш корисна адаптація BEM CSS

IE11 виконує деяку підтримку CSS-сітки, але не підтримує grid-gap або автоматичне розміщення. Після того, як деякі слабаки лаються і хочуть, щоб люди оновили свої браузери, ви налаштовуєте стилі, щоб вони виглядали наступним чином:

Тепер він виглядає в IE ідеально. І з світом все в порядку. Що ж могло піти не так?

Через пару годин помістіть цей компонент button в інший компонент на сайті. Цей інший компонент також використовує css-grid для компонування своїх дочірніх елементів.

Тепер пишете наступний код:

Передбачається, що ми побачимо макет, який виглядає ось так навіть в IE11:

ABEM. Більш корисна адаптація BEM CSS

Але замість цього, за grid-column: 3; код, який був написаний раніше, виглядає наступним чином:

ABEM. Більш корисна адаптація BEM CSS

Отже, що ми робимо з цим grid-column: 3;CSS, який ми написали раніше? Нам потрібно обмежити його батьківським компонентом, але як?

Класичний метод BEM, пов’язаний з цим, полягає в тому, щоб додати новий елемент класу батьківських компонентів button:

На перший погляд це рішення виглядає досить добре:

Він зберігає визначеність низькою

Батьківський компонент контролює свій власний макет

Стилізація навряд чи буде кровоточити інші компоненти, які ми не хочемо, щоб вони спливали кров’ю

Всі приголомшливо, і все в порядку з світом … вірно?

Недоліком цього підходу в основному є те, що нам довелося додати додатковий клас до компонента button. Оскільки subscribe-form__submit клас не існує в базовому button компоненті, це означає, що нам потрібно додати додаткову логіку до того, що ми використовуємо в якості нашого механізму шаблонів для отримання правильних стилів.

Мені подобається використовувати Pug для створення шаблонів сторінок. В якості прикладу я покажу вам, що я маю на увазі під використанням Pug mixins.

По-перше, ось оригінальний недружній код IE, переписаний у форматі mixin:

Тепер додамо до цього subscribe-form__submit класу IE 11:

Це було не так складно, тому навіщо я скаржуся? Ну, скажімо так, іноді ми хочемо, щоб цей модуль розміщувався всередині бічній панелі. Коли це так, ми хочемо, щоб вхід електронної пошти і кнопка були покладені один на одного. Пам’ятайте, що для суворого дотримання BEM нам не дозволено використовувати що-небудь більш високу по специфічності, ніж один клас у наших стилях.

Цей код Pug виглядає не так просто, правда? Є кілька речей, які сприяли цьому безладу.

Контейнерні запити зроблять це менш проблематичним, але вони існують в кожному браузері

Проблеми навколо синтаксису модифікатора BEM виховують їх потворні голови.

Тепер спробуйте зробити це знову, але на цей раз з використанням контекстно-залежних стилів:

Подивіться, наскільки простіше стало розмітка Pug. Немає ніякої «якщо це, то те» логіки, про яку потрібно турбуватися. Вся батьківська логіка передається в css, та набагато краще розуміє, які елементи є батьками інших елементів.

Можливо, ви помітили, що в останньому прикладі я використовував селектор, який був трьома класами. Він був використаний для застосування 100% ширини до кнопки. Так, селектор трьох класів це вірне рішення, якщо ви можете його аргументувати.

Я не хотів, щоб 100% ширина застосовувалася до кнопку кожен раз, коли вона:

використовується скрізь

поміщається всередині форми підписки

розміщена всередині бічній панелі

Я хотів використовувати ширину 100%, тільки коли вона була всередині форми підписки або всередині бічній панелі. Кращим способом впоратися з цим був з селектором трьох класів.

Насправді, я б швидше використовував клас verticalStack-модифікатора стилю ABEM для subscribe-form елемента, щоб застосувати стилі вертикального стека, чи, можливо, навіть виконати його через запити елементів з допомогою EQCSS. Це означало б, що я можу застосовувати вертикальні стилі стека в більшій кількості ситуацій, ніж коли він знаходиться на бічній панелі. Однак для прикладу я зробив як контекстно-залежні стилі.

Тепер, коли ми розуміємо контекстно-залежні стилі, повернемося до того оригінальному наприклад, який у мене був, і використовуємо деякі контекстно-залежні стилі для застосування того самого grid-column: 3правила:

Контекстно-залежні стилі призводять до спрощення логіки HTML шаблонів, зберігаючи при цьому повторне використання дочірніх компонентів. Тим не менш, один клас класу BEM для кожної селекційної філософії не дозволяє цьому статися.

Оскільки контекстно-залежні стилі в першу чергу стосуються макета, потрібно використовувати їх кожного разу, коли стосується цих властивостей CSS, залежно від обставин:

Будь-яка пов’язана з CSS сітка, яка застосовується до дочірнього елемента ( grid-columnи grid-rowт. д.),

Будь пов’язане з Flexbox, яке застосовується до дочірнього елемента ( flex-grow, flex-shrink та align-self тощо),

margin значення більше 0

positionкроме значення relative(поряд з top, left, bottom right властивостей)

transform якщо він використовується для позиціонування translateY

Ви також можете помістити ці властивості контекстно-залежні стилі, але вони не так часто необхідні в контексті, чутливому до контексту.

width

height

padding

border

Щоб все остаточно стало ясно, контекстно-залежні стилі не гніздяться заради гніздування. Потрібно думати про них, як ніби це if заяву в JavaScript.

Отже, правила CSS:

.parent .element { /* context sensitive styles */}

Думайте про це, неначе пишете наступну логіку:

if (.element in .parent) { .element { /* context sensitive styles */ } }

Також розумійте, що написання такого правила, як це має три рівня:

.grandparent .parent .element { /* context sensitive styles */ }

Слід думати, що ви пишете логіку наступним чином:

if ( (.element in .parent) && (.element in .grandparent) && (.parent in .grandparent) ) { .element { /* context sensitive styles */ } }

Тому, у що б то не стало, напишіть селектор css, який знаходиться на трьох рівнях, якщо ви дійсно вважаєте, що вам потрібен такий рівень специфічності. Будь ласка, зрозумійте основну логіку css, яку пишете. Використовуйте тільки той рівень специфічності, який має сенс для конкретного стилю, якого ви намагаєтеся досягти.

І знову, ще раз, просто щоб було зрозуміло, гніздяться не заради гніздування!

Підведення підсумків

Методологія угоди про імена BEM — це те, що я повністю схвалюю. Вона дозволяє css розбиватися на невеликі легко керовані компоненти, а не залишати css громіздкою безладної високої специфічності, яку важко підтримувати. Проте бажано, щоб це був офіційний синтаксис BEM.

Офіційний синтаксис BEM:

Не підтримує Atomic Design

Важко продовжується

Займає більше часу, щоб ваш розум обробляв угруповання імен класів

Є жахливо некомпетентним, коли справа торкається управління станом на великих компонентах

Намагається спонукати вас використовувати окремі селектори класів, коли подвійні селектори класів призводять до спрощення обслуговування

Намагається дати простір імен всім, навіть якщо це викликає більше проблем, ніж вирішує.

Робить HTML надзвичайно роздутим, коли він зроблений правильно

Неофіційний ABEM:

Спрощує роботу з Atomic Design

Викидає символ тире як додатковий метод, який можна використовувати для групування

Дозволяє вашому розуму швидше обробляти угруповання імен класів

Відмінно підходить для управління станом будь-якого компонента, незалежно від того, скільки компонентів

Заохочує контрольовану специфіку, а не просто пряму низьку специфіку, щоб пом’якшити плутанину в команді і поліпшити підтримку сайту

Усуває простір імен, коли воно не потрібне

Зберігає HTML досить чистим з мінімальними додатковими класами, застосовуваними до модулів, зберігаючи при цьому всі переваги BEM

Відмова від відповідальності

Це не я придумав -modifier (єдина тире перед ім’ям модифікатора) ідею. Я виявив її в 2016 році в одній статті і не пам’ятаю, хто спочатку цю ідею концептуализировал. Але я буду радий допомогти їм, якщо хто-небудь знає статтю.