В першу чергу варто зафіксувати, що Україна не Росія, а CSS не стилі. А інструмент для структурованого їх опису. Стилі ж — це безпосередньо правила, які застосовуються до елементів. Тобто CSS це те, що ми пишемо, стилі — те, що бравзер мастить на DOM.
CSS це не лише мова, а й певні концепції, і найголовніша з яких, про яку усі чомусь забувають — це, власне, каскадність. Якщо коротко, то каскадність — це правила, за якими визначається пріоритетність застосування стилів до елемента, і враховує вона не лише специфічність.
Найперше, що береться до уваги — походження. Бравзери розрізняють три головні джерела стилів: вбудовані бравзерні, користувацькі та авторські.
З вбудованими все ясно — це стилі за замовчуванням, які вшиті в сам бравзер. Користувацькі — це налаштування, задані користувачем через бравзер, або через плагіни, наприклад, для покращення доступності. Ну а авторські стилі пишуть, власне, розробники сайтів.
І найперше каскад бере до уваги саме походження: спершу бравзерні стилі, далі користувацькі, і наприкінець авторські.
До речі, чому саме каскад? Якщо уявити собі цю схему як водоспадик, то виглядатиме вона так:
[user-agent styles]
↳[user styles]
↳[author styles]
І в такій ієрархії пріоритет надається стилям, що знаходяться нижче за каскадом. Така собі спадна ієрархія.
Дуже важлива ремарка: це класична модель без !important. З ним user styles важливіші за author styles. Але я це не розглядаю детальніше, бо за !important треба звільняти з доганою і відбирати назавжди ліцензію на написання CSS.
Добре, з походженням розібрались. Далі йде специфічність селектора. Вона працює тільки всередині одного походження, тож більш специфічне правило нижчого походження програє менш специфічному вищого походження. Як у житті.
І вже аж потім, якщо раптом у нас є декілька декларацій з однаковою специфічністю, використовується правило "хто останній, той і
Якщо ви досі не поставили вогник і не поширили цей допис, знайте — я на вас образився.
А чого ж я вжив вираз "класична модель"? Бо тепер у нас є ще один нюанс, на який треба звертати увагу, і це надзвичайно потужний інструмент для керування каскадом саме нами, розробниками.
Мова йде про
@layer. По суті, це ще один рівень в межах origin, який дозволяє нам точніше групувати визначення і, що найголовніше, керувати порядком застосування цих груп. Що важливо, специфічність в шарах також ізольована, тому важкий селектор з одного шару може бути дуже легко перебитий легеньким селектором з іншого:@layer base, override;
@layer override {
p { color: red; }
}
@layer base {
#foo { color: lime; }
}
В цьому випадку текст
<p id="foo">hello</p> буде не зелений, а червоний, хоча, як ми знаємо, id набагато важчий за селектор тега.Таким чином можна дуже тонко налаштовувати каскадність, не переживаючи за те, що треба буде перебивати специфічність якогось селектора вручну, достатньо просто правильно організувати порядок цих шарів.
Я особливо оцінив цей підхід у дизайн-системах: стилі легко розбивати на логічні групи — tokens, base, typography, components, overrides. І завжди зрозуміло, в якому порядку вони застосуються, без страху, що десь у глибині з’явиться монстр-селектор на десяток класів і ID, згенерований JavaScript, і доведеться з ним воювати.
***
Специфікації W3C
CSS Cascading and Inheritance Level 4 — Cascading Order
CSS Cascading and Inheritance Level 5 — Cascade Layers
Документація MDN
Cascade and inheritance
Cascade layers
Статті людською мовою
Getting Started With CSS Cascade Layers
CSS Cascade Layers
***
А ви як, пробували вже, використовували? Чи чуєте вперше, і вже не можете дочекатися, аби запушити це в прод? Розказуйте.
@babichdev