No history yet

Каскадні шари @layer

Керування каскадом за допомогою @layer

Уявіть, що ви працюєте над великим проєктом. У вас є базові стилі для HTML-тегів, стилі для компонентів (кнопки, картки) та утилітарні класи (наприклад, text-center). Рано чи пізно виникає конфлікт: стиль утиліти не може перевизначити стиль компонента, хоча ви цього очікуєте. Це класична війна специфічності, яку раніше вирішували за допомогою !important або складних селекторів.

/* Старий підхід: підвищення специфічності */
.card button.primary {
  background-color: blue; /* Специфічність: 0,2,1 */
}

.btn-danger {
  background-color: red; /* Специфічність: 0,1,0 - не спрацює */
}

/* Або ще гірше */
.btn-danger {
  background-color: red !important; 
}

Каскадні шари (@layer) пропонують елегантне рішення. Вони дозволяють вам групувати CSS-правила в окремі шари. Головна перевага в тому, що пріоритет шару важливіший за специфічність селектора всередині нього. Це дає вам повний контроль над тим, які стилі переможуть.

Оголошення та порядок шарів

Найважливіше правило шарів — їхній порядок. Ви можете (і повинні) визначити порядок пріоритетності всіх шарів на самому початку вашого CSS-файлу. Шари, оголошені пізніше, мають вищий пріоритет. Стилі в шарі utilities завжди переможуть стилі в шарі components, незалежно від специфічності селекторів.

@layer reset, base, components, utilities;

/* Тепер можна додавати стилі до цих шарів у будь-якому порядку */
@layer components {
  .button {
    padding: 1rem 2rem; /* Специфічність: 0,1,0 */
  }
}

@layer utilities {
  .p-0 {
    padding: 0; /* Специфічність: 0,1,0 */
  }
}

/*
  Кнопка з класами <button class="button p-0"> матиме padding: 0,
  оскільки шар utilities має вищий пріоритет, ніж components.
*/

Також можна створювати анонімні шари, просто обгортаючи стилі в @layer { ... }. Їхній пріоритет визначається порядком появи у файлі, але вони завжди матимуть нижчий пріоритет, ніж будь-які іменовані шари.

Взаємодія з іншими стилями

Що відбувається, коли одні стилі знаходяться в шарі, а інші — ні? Правило просте: стилі поза шарами (unlayered styles) завжди перемагають стилі в шарах.

Це зроблено для зворотної сумісності. Ваш існуючий код, написаний без @layer, продовжить працювати, як очікувалося, і матиме найвищий пріоритет, що дозволяє поступово впроваджувати шари у проєкт.

Тип стилюПріоритет (від найнижчого до найвищого)
Стилі в шарахВідповідно до порядку @layer
Стилі поза шарамиЗавжди вищий, ніж у будь-якого шару

А як щодо !important? Це правило все ще залишається найвищим авторитетом, але воно також враховує шари. !important у шарі з вищим пріоритетом переможе !important у шарі з нижчим. І, звісно, !important поза шарами переможе будь-який !important всередині шару. Це створює нові «шари» пріоритетності для !important.

Вкладені шари

Для складних дизайн-систем можна створювати вкладені шари. Це дозволяє детальніше організувати стилі всередині одного великого шару. Вкладеність створюється за допомогою крапкової нотації. Наприклад, ви можете створити шар components, а всередині нього — підшари buttons та cards.

@layer components, components.buttons, components.cards;

/* Або так: */
@layer components {
  /* Стилі для всіх компонентів */

  @layer buttons {
    /* Стилі тільки для кнопок */
    .btn { ... }
  }

  @layer cards {
    /* Стилі тільки для карток */
    .card { ... }
  }
}

Порядок вкладених шарів також важливий. Якщо ви оголосили @layer components.cards, components.buttons;, то стилі для кнопок матимуть вищий пріоритет, ніж стилі для карток усередині шару components. Це дає гранулярний контроль над архітектурою ваших стилів.

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

Quiz Questions 1/5

Яку основну проблему вирішують каскадні шари (@layer) в CSS?

Quiz Questions 2/5

Розгляньте наступний CSS код. Якого кольору буде текст у параграфі з класом .important-text?

@layer base, components, utilities;

@layer base {
  p { color: blue; }
}

@layer utilities {
  .important-text { color: green; }
}

#main-content .important-text { color: red; }