Модуль 1 · урок 8 з 14
Каскад і специфічність
Це та секція, після якої зникає потреба в !important. Питання «чому мій стиль
не застосувався» завжди має одну з трьох відповідей: селектор програв за специфічністю,
програв за порядком, або взагалі не збігся.
Як рахується вага селектора
Специфічність — це трійка чисел (A, B, C). Порівнюються зліва направо, як версія програми: якщо A більше — далі можна не дивитись.
#id сильніший за десять класів.
Тому «важкі» селектори з id — головна причина, через яку далі доводиться писати !important.Порядок правил у каскаді
Коли специфічність однакова, виграє те, що нижче в коді. Повний порядок ухвалення рішення, згори вниз:
- Чи збігся селектор узагалі.
- Шар каскаду (
@layer), якщо використовується. !important— перевертає все з ніг на голову.- Специфічність (A, B, C).
- Порядок у файлі: хто пізніше, той і правий.
Як писати так, щоб не воювати з каскадом
- Один клас — один компонент:
.card,.card__title. - Селектор завглибшки максимум два рівні.
- Модифікатор — теж клас:
.btn--ghost, а не.panel .btn. - Для стилів «за замовчуванням» —
:where(), щоб їх легко перебивати. - Порядок файлів: спершу базове, потім компоненти, потім утиліти.
- Стилі по
#id. - Ланцюги
.a .b .c .dз вкладеності SCSS. - Інлайн-стилі з шаблону.
- Перебивання чужої бібліотеки «зверху» замість налаштування її токенів.
- Утиліти, підключені раніше за компоненти.
:is(), :where() і @layer
/* :is() групує й бере НАЙБІЛЬШУ вагу зі списку */
:is(h1, h2, h3) .lead { } /* = (0,1,0) + вага найважчого в дужках */
/* :where() групує, але його власна вага = 0 */
:where(.prose) p { margin-block: 1em; } /* (0,0,1) — перебити зможе навіть .p */
/* @layer задає пріоритет груп; шар, оголошений пізніше, сильніший */
@layer base, components, utilities;
@layer base { button { font: inherit; } }
@layer components { .btn { padding: 8px 14px; } }
@layer utilities { .mt-0 { margin-top: 0; } } /* переможе .btn, хоч вага однакова */
Практично: :where() — для скидань і базових стилів, які завжди мають легко
перебиватись. @layer — коли в проєкті є і своя бібліотека, і утиліти,
і треба раз і назавжди зафіксувати, хто кого перебиває.
Якщо колись доведеться його поставити (а в чужих віджетах доводиться), правильна формула:
«тут !important, бо стиль приходить інлайном зі сторонньої бібліотеки, і перебити
його інакше не можна». Це технічна причина. А от «інакше не працювало» — це не причина,
і саме так це почує лід.