Сучасний CSS Майстерність 2025
Каскадні шари @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, який вирішує давню проблему управління специфічністю. Вони дозволяють будувати передбачувані та масштабовані стильові архітектури.
Яку основну проблему вирішують каскадні шари (@layer) в CSS?
Розгляньте наступний CSS код. Якого кольору буде текст у параграфі з класом .important-text?
@layer base, components, utilities;
@layer base {
p { color: blue; }
}
@layer utilities {
.important-text { color: green; }
}
#main-content .important-text { color: red; }