Черговість CSS (коли порядок в CSS має значення)

320

Від автора: зазвичай, коли ви пишіть стилі, ви навіть не замислюєтеся про черговості в CSS. Дотримання черговості не сама пріоритетна задача, але все ж вона має значення! Черговість працює, коли є однакові селектори і елементи з однаковою специфічністю. Якщо специфічність повністю збігається, то порядок стилів має значення. Застосовуються більш пізні стилі.

В одному файлі стилів

Приміром, у нас є HTML код:

Document

Module

Порядок атрибутів у HTML не грає ніякої ролі, а от порядок в стилях дуже важливий. Розберемо властивість background:

/*
Всі селектори збігаються
І володіють однаковою специфічністю
*/
.module {
background: #ccc;
padding: 20px;
max-width: 400px;
margin: 20px auto;
}
.module-foo {
background: orange;
}
/* Перемагають ОСТАННІ оголошення */
.module-bar {
background: lightblue; /* Я виграв! */
/* Інші стилі */
}

Спеціально заплутаний приклад

Порядок не обмежується тільки одним оголошенням стилів. Ще більш важливий порядок оголошення стилів в документі.
Зверніть увагу на документ нижче з трьома різними оголошеннями стилів. Назвемо їх шматочками. Ці шматочки — це , блок style і @import.

Document
.module-baz {
background-color: pink;
}

Module

@import “2.css”;
/*
Contains
.module-bar { background: #f06d06; }
*/

Я позначив наші шматочки #1, #2 і #3. Всі вони містять селектори з однаковою специфічністю. Шматочок #3 оголошений останнім, а значить, він перемагає.

Асинхронно завантажувані стилі CSS теж дотримуються черговість

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

Завантажувач loadCSS за замовчуванням вставляє стилі в кінець тегу head. Тобто цей файл стане #3, а блок style перед закриваючим тегом body перетвориться у #4. Шматочок #4 в такому разі виграє.

Document
loadCSS(“2.css”);

Module

Насправді, не можна вставляти теги link і style в тег body (хоч це і працює). Ймовірність того, що завантажені за допомогою loadCSS стилі не спрацюють, вкрай мала. Можна вказати ID, щоб контролювати порядок CSS:

// файл CSS буде завантажений прямо перед тегом script з цим кодом
loadCSS(“path/to/mystylesheet.css”, document.getElementById(“loadcss”));

Дивний критичний CSS

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

Document
/* #1
Критичний CSS код */
/* #2
Завантажуємо залишився CSS
*/

Module

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

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

Дивні розширення

Розширення в препроцессорах ведуть себе дивно. Наприклад, ви хочете по-різному стилізувати елемент:

Module

Код препроцесора буде таким (супер спрощений код чисто для демо):

%variation {
background: orange;
}
.module {
background: #ccc;
padding: 20px;
max-width: 400px;
margin: 20px auto;
}
.module-variation {
@extend %variation;
}

Ви можете подумати: «добре, .module-variation оголошений ОСТАННІМ, він виграє, фон буде помаранчевим». Це не так, оскільки розширення переміщує селектор в те місце, де розширення було оголошено. У нашому випадку це місце знаходиться перед стилями, якими ми намагалися переписати фон. Скомпільований CSS код:

.module-variation {
background: orange;
}
.module {
background: #ccc;
padding: 20px;
max-width: 400px;
margin: 20px auto;
}

Властивість background прийме значення #ccc, а не те, що ми хочемо. Напевно, простіше таку проблему вирішити при допомоги специфічності, а не черговості стилів. Рідні розширення, коли будуть введені, будуть менш заплутаними.

Досить заплутаний механізм

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