Critical CSS — минимальный набор стилей, нужный для отрисовки контента в первом видимом экране (above the fold). Вставляется прямо в шапку HTML как <style>, чтобы браузер не ждал загрузки внешнего CSS-файла перед первой отрисовкой.
Остальной CSS загружается асинхронно через rel="preload" с onload. Так выигрываем 200–500 мс к LCP и FCP на типичных страницах. Размер инлайн-блока — обычно 4–14 КБ (один TCP-сегмент).
<!-- Inline критический CSS для первого экрана --> <style> body { font-family: system-ui; margin: 0; } .hero { padding: 48px 24px; background: #faf9f5; } .hero h1 { font-size: 48px; line-height: 1.1; } </style> <!-- Остальной CSS — async --> <link rel="stylesheet" href="/main.css" media="print" onload="this.media='all'">
Главная страница pawetta.com: ~4 КБ критичного CSS встроены инлайн, остальные 108 КБ pages.css грузятся через preload — LCP стал 1,4 с вместо 2,1 с.
Главная ловушка инлайна — поддержка. Critical CSS привязан к конкретной вёрстке первого экрана, и стоит сменить шаблон шапки или баннер, как встроенный блок устаревает: на странице появляется FOUC (мелькание нестилизованного контента) или, наоборот, видимый сдвиг при подгрузке основного файла, что бьёт уже по CLS. Поэтому критический CSS пересобирают на каждом деплое инструментами вроде Critical, Penthouse или критикал-плагинов сборщика, прогоняя их на нужных вьюпортах. Руками раз и навсегда его не написать.
Второй подвох — асинхронная загрузка остального CSS. Трюк с preload + onload (переключение rel на stylesheet после загрузки) требует noscript-фолбэка, иначе при выключенном JS страница останется без полных стилей. И инлайн нельзя кэшировать отдельно: эти 4–14 КБ браузер тянет с каждым HTML-документом заново, так что раздувать блок выше одного TCP-сегмента (~14 КБ) контрпродуктивно — выигрыш в первой отрисовке съедается лишним весом ответа и ростом TTFB на медленном сервере.
Минимальный набор правил для отрисовки видимой части страницы без обращения к внешнему файлу.
Встраивается тегом в HTML, а полный CSS грузится асинхронно через preload с onload-переключением на stylesheet.
Убирает render-blocking-запрос к CSS из критического пути, выигрывая 200–500 мс к первой отрисовке.
Собрать критический CSS помогает вкладка Coverage в DevTools: она показывает, какая часть каждого файла стилей реально применилась на странице. Дальше выбор между генераторами и руками. Автоматика хорошо работает на однотипных шаблонах и спотыкается на страницах с разной вёрсткой: под каждый тип шаблона нужен свой набор, иначе на карточке товара окажутся стили главной. Держать один общий критический блок на весь сайт проще в поддержке и почти всегда достаточно.
Побочный эффект — рассинхрон при обновлении дизайна. Инлайновые стили лежат внутри HTML, и когда меняется внешний файл, встроенный кусок остаётся старым: на первой отрисовке страница показывает прежний макет, потом перепрыгивает в новый. Лечится тем, что критический блок пересобирается тем же скриптом, который выкатывает стили, и версия внешнего файла бампается в один момент с ним. Ручная правка одного из двух мест — самая частая причина мигания вёрстки после релиза.
Смысл появляется не всегда. Когда весь CSS сайта весит меньше 14 килобайт в сжатом виде, он умещается в первый пакет ответа и приезжает вместе с HTML — тогда проще встроить его целиком и не городить сборку. Выигрыш заметен на тяжёлых теми, где стилей на сотни килобайт и в первый экран из них попадает пятая часть; там разница на LCP измеряется сотнями миллисекунд.