Пошук уроків, статей та іншого контенту
Оптимізуємо CSS за допомогою видалення зайвого коду, мініфікації, критичних стилів і контролю розміру файлів.
CSS впливає на кілька етапів завантаження сторінки:
Браузер завантажує CSS-файли.
Створює CSSOM — об’єктну модель стилів.
Об’єднує DOM і CSSOM у render tree.
Виконує layout і paint.
Перемальовує сторінку після змін стилів.
Звичайний CSS-файл є ресурсом, який може блокувати перше відображення сторінки. Поки браузер не завантажить і не обробить таблиці стилів, він не завжди може безпечно показати сторінку користувачу.
На продуктивність впливають:
розмір CSS-файлів;
кількість CSS-файлів;
наявність невикористаних правил;
складність селекторів;
кількість стилів, які потрібні для першого екрана;
спосіб завантаження критичних і другорядних стилів.
Оптимізація CSS не означає механічне видалення всіх правил або написання максимально коротких селекторів. Потрібно зменшити обсяг даних і кількість непотрібної роботи браузера, не змінюючи поведінку інтерфейсу.
У великих проєктах CSS часто містить правила, які залишилися після видалення компонентів або використовуються лише на окремих сторінках.
Наприклад:
/* Використовується на сторінці */
.card {
padding: 1rem;
}
/* Старий компонент, якого вже немає в HTML */
.old-product-widget {
display: flex;
border: 1px solid #ddd;
}
/* Стан, який більше не реалізований у JavaScript */
.modal.is-visible {
opacity: 1;
}Невикористаний CSS:
збільшує розмір файлу;
довше передається мережею;
потребує додаткового аналізу браузером;
ускладнює підтримку;
збільшує ризик конфліктів між стилями.
Для ручного аналізу можна використовувати вкладку Coverage у DevTools браузера Chromium:
Відкрийте DevTools.
Відкрийте меню команд.
Запустіть інструмент Coverage.
Перезавантажте сторінку.
Перегляньте, які частини CSS не використовувалися під час сценарію.
Coverage показує використання стилів лише під час конкретного сценарію. Якщо користувач не відкрив меню, модальне вікно або іншу сторінку, їхні стилі можуть помилково виглядати невикористаними.
Тому перед видаленням потрібно перевірити:
усі маршрути застосунку;
стани компонентів;
hover-, focus- і disabled-стани;
класи, які додаються JavaScript;
класи, що формуються динамічно;
стилі для помилок і порожніх станів;
адаптивні брейкпойнти.
Інструменти очищення CSS зазвичай аналізують HTML, шаблони та JavaScript, а потім залишають лише знайдені селектори. Це ефективно для статичних класів:
<button class="button button--primary">Зберегти</button>Але динамічний код може створити клас, якого немає в початкових файлах:
const color = "success";
element.className = "alert alert--" + color;Автоматичний аналіз може не зрозуміти, що потрібен селектор .alert--success. Для таких випадків використовують:
явні списки дозволених класів;
safelist у конфігурації інструмента;
стабільні повні назви класів у коді;
перевірку всіх важливих сценаріїв після очищення.
Не слід видаляти CSS лише на основі одного запуску тестів або одного перегляду сторінки.
Повторювані декларації збільшують файл і ускладнюють подальші зміни.
До оптимізації:
.header {
color: #1f2937;
background-color: #ffffff;
}
.card {
color: #1f2937;
background-color: #ffffff;
}
.footer {
color: #1f2937;
background-color: #ffffff;
}Після оптимізації:
.header,
.card,
.footer {
color: #1f2937;
background-color: #ffffff;
}Однак об’єднання селекторів має сенс лише тоді, коли правила справді належать до одного рівня абстракції та мають однакову поведінку.
Замість великої кількості майже однакових правил можна використовувати CSS-змінні:
:root {
--color-text: #1f2937;
--color-surface: #ffffff;
--space-md: 1rem;
}
.card {
color: var(--color-text);
background-color: var(--color-surface);
padding: var(--space-md);
}CSS-змінні не завжди зменшують мініфікований файл, але допомагають уникати розходження значень і спрощують підтримку стилів.
Мініфікація видаляє з CSS те, що не потрібне браузеру для обчислення стилів:
пробіли;
переноси рядків;
коментарі;
зайві крапки з комою;
частину необов’язкових символів.
До мініфікації:
/* Основна кнопка */
.button {
display: inline-block;
padding: 0.75rem 1rem;
color: #ffffff;
background-color: #2563eb;
}Після мініфікації:
.button{display:inline-block;padding:.75rem 1rem;color:#fff;background-color:#2563eb}Мініфікований CSS не потрібно редагувати вручну. Зберігайте читабельний вихідний файл, а мініфіковану версію створюйте під час production-збірки.
У production-процесі потрібно перевіряти:
чи не видаляються потрібні правила;
чи зберігаються CSS-коментарі, якщо вони потрібні інструментам;
чи генерується source map для налагодження;
чи мініфікуються тільки production-файли;
чи результат проходить автоматичні тести та візуальну перевірку.
Мініфікація зменшує обсяг файлу, але не видаляє невикористаний CSS. Це різні етапи:
видалення зайвих правил;
оптимізація структури;
мініфікація;
стиснення під час передавання мережею.
Критичні стилі — це мінімальний набір CSS, необхідний для відображення першого видимого екрана.
До нього можуть належати:
базові стилі body;
шапка;
основний заголовок;
початковий layout;
видимий блок контенту;
стилі завантажувача або placeholder.
Стилі для нижньої частини сторінки, закритого меню чи модального вікна не обов’язково потрібні до першого відображення.
Критичні стилі можна розмістити безпосередньо в <head>:
<!doctype html>
<html lang="uk">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
:root {
font-family: system-ui, sans-serif;
color: #172033;
background: #ffffff;
}
body {
margin: 0;
}
.site-header {
min-height: 4rem;
display: flex;
align-items: center;
padding: 0 1.5rem;
border-bottom: 1px solid #e5e7eb;
}
.hero {
max-width: 48rem;
margin: 0 auto;
padding: 4rem 1.5rem;
}
.hero h1 {
margin: 0;
font-size: clamp(2rem, 5vw, 4rem);
line-height: 1.1;
}
</style>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<header class="site-header">
<strong>Fullstack</strong>
</header>
<main class="hero">
<h1>Оптимізований інтерфейс</h1>
<p>Критичні стилі відображаються одразу.</p>
</main>
</body>
</html>Такий підхід дозволяє браузеру відобразити базову структуру без очікування окремого CSS-файлу.
Критичні стилі повинні бути невеликими. Якщо вставити в HTML весь CSS, файл документа стане більшим, а перевага зникне.
Якщо частину стилів потрібно завантажити після першого відображення, можна використати preload:
<link
rel="preload"
href="/styles.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
>
<noscript>
<link rel="stylesheet" href="/styles.css">
</noscript>preload повідомляє браузеру, що ресурс потрібно завантажити раніше, але спочатку він не застосовує його як таблицю стилів. Обробник onload змінює значення rel на stylesheet.
Цей підхід потрібно тестувати на реальних сторінках. Неправильно відкладені стилі можуть спричинити:
коротке відображення неоформленого HTML;
стрибки layout;
пізню зміну шрифтів або розмірів блоків;
складнішу логіку завантаження.
Для простих сторінок звичайний <link rel="stylesheet"> часто є надійнішим рішенням.
Розмір CSS потрібно контролювати автоматично, а не перевіряти лише перед релізом.
Корисно визначити окремі обмеження для:
критичних стилів;
основного CSS-файлу;
CSS окремої сторінки;
загального обсягу стилів, який завантажує маршрут.
Наприклад, у CI можна перевіряти розмір production-файлу:
// Перевірка, що CSS-файл не перевищує встановлений бюджет
import { stat } from "node:fs/promises";
const filePath = "dist/styles.min.css";
const maximumBytes = 100 * 1024;
const { size } = await stat(filePath);
if (size > maximumBytes) {
console.error(
`CSS-файл завеликий: ${size} байт, максимум — ${maximumBytes} байт`
);
process.exit(1);
}
console.log(`Розмір CSS відповідає бюджету: ${size} байт`);Запустити файл можна командою:
node check-css-size.mjsТакий скрипт перевіряє фактичний розмір файлу на диску. Для оцінювання швидкості передавання також потрібно враховувати стиснення Brotli або gzip.
Не варто орієнтуватися лише на розмір мініфікованого файлу. Важливі також:
розмір після стиснення;
кількість запитів;
час завантаження;
час обробки CSS;
зміни layout після завантаження;
поведінка на повільній мережі та слабкому пристрої.
Для існуючого проєкту зручно використовувати такий порядок:
Зафіксувати поточні показники.
Знайти великі CSS-файли.
Перевірити невикористані правила.
Видалити застарілі компоненти та дублювання.
Розділити стилі за сторінками або функціональними частинами.
Визначити критичні стилі першого екрана.
Налаштувати production-мініфікацію.
Встановити бюджети розміру.
Перевірити адаптивність і динамічні стани.
Повторно виміряти результат.
Не слід оптимізувати селектори лише за їхньою довжиною. Різниця між .card і main .page .content .card може бути корисною для читабельності, але найбільший ефект зазвичай дає видалення непотрібних правил і зменшення файлів.
Сторінка може виглядати правильно, але інший маршрут або стан компонента залишиться без стилів.
Стилі класів, створених JavaScript або серверним шаблоном, можуть бути видалені під час збірки.
Це зменшує кількість окремих запитів, але збільшує HTML-документ і не дозволяє повторно кешувати CSS між сторінками.
preload без перевіркиНеправильне відкладене завантаження може спричинити мерехтіння, layout shift або пізнє оформлення сторінки.
Для production важливі результати після очищення, мініфікації та стиснення.
Потрібно перевірити не тільки головну сторінку, а й:
різні розміри екрана;
клавіатурну навігацію;
hover і focus;
відкриті меню;
помилки форм;
модальні вікна;
порожні стани;
темну тему, якщо вона підтримується.
Видаляйте CSS, який більше не використовується, але враховуйте динамічні стани та всі маршрути.
Не плутайте очищення CSS з мініфікацією: перше видаляє непотрібні правила, друге зменшує запис уже потрібного коду.
Виносьте стилі першого екрана до критичного набору, але не вбудовуйте весь CSS у HTML.
Обережно використовуйте відкладене завантаження таблиць стилів.
Встановлюйте бюджети для production-файлів і перевіряйте їх у CI.
Оцінюйте не лише байти, а й стиснення, час завантаження, обробку стилів і стабільність layout.
Після кожної оптимізації перевіряйте всі компоненти, маршрути та динамічні стани.