Критический CSS — inline critical CSS

Критический CSS (Critical CSS) — стили, необходимые для рендеринга контента выше fold (above the fold). Их встраивают inline в <head> для устранения блокирующих рендер внешних CSS-файлов, что ускоряет FCP и LCP.

Зачем нужно

Внешние CSS-файлы блокируют рендер: браузер не показывает ничего, пока не загрузит и не разберёт все CSS из <head>. Inline critical CSS → браузер рендерит первый экран немедленно, а полный CSS загружается асинхронно. Типичный эффект: FCP -300-800ms.

Где используется

  • Маркетинговые лендинги и страницы с высоким показателем отказов
  • Страницы с большим CSS (>50KB) из-за CSS фреймворков (Tailwind, Bootstrap)
  • AMP-страницы (critical CSS обязателен по спецификации)
  • Любой сайт с целью улучшить FCP/LCP

Основной контент

Что такое Critical CSS

<!-- БЕЗ Critical CSS: рендер заблокирован -->
<head>
  <link rel="stylesheet" href="/css/main.css"> <!-- Блокирует! -->
</head>

<!-- С Critical CSS: первый экран сразу -->
<head>
  <style>
    /* ~14KB критических стилей inline */
    .hero { background: #1a1a2e; color: white; padding: 4rem; }
    .nav { display: flex; justify-content: space-between; }
    .btn-primary { background: #e94560; padding: 1rem 2rem; }
  </style>
  <!-- Полный CSS асинхронно (не блокирует!) -->
  <link rel="preload" href="/css/main.css" as="style"
        onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/css/main.css"></noscript>
</head>

Автоматическое извлечение через Critical (CLI)

npm install -g critical

# Извлечь критический CSS для конкретной страницы
critical https://example.com \
  --base dist/ \
  --css dist/css/main.css \
  --width 1300 \
  --height 900 \
  --inline \
  --target dist/index.html

Интеграция в Vite/Webpack build

// vite.config.js с плагином vite-plugin-critical
import { defineConfig } from 'vite';
import critical from 'vite-plugin-critical';

export default defineConfig({
  plugins: [
    critical({
      criticalUrl: 'http://localhost:4173',
      criticalBase: 'dist',
      criticalPages: [
        { uri: '/',         template: 'index' },
        { uri: '/products', template: 'products' },
      ],
      criticalConfig: {
        width: 1300,
        height: 900,
        penthouse: { timeout: 30000 },
      },
    }),
  ],
});

Next.js: автоматический Critical CSS

// next.config.js
// Next.js автоматически инлайнит critical CSS для каждой страницы
// через оптимизацию на этапе сборки

// Для Tailwind — purge + critical inline встроены
/** @type {import('next').NextConfig} */
module.exports = {
  experimental: {
    optimizeCss: true, // Включает @vercel/og оптимизацию
  },
};

Загрузка не-критического CSS асинхронно

<!-- Паттерн preload + onload trick -->
<link
  rel="preload"
  href="/css/full.css"
  as="style"
  onload="this.onload=null; this.rel='stylesheet'"
>
<!-- Fallback без JavaScript -->
<noscript>
  <link rel="stylesheet" href="/css/full.css">
</noscript>

Частые ошибки

  • Слишком большой "критический" CSS (>20KB) — нивелирует преимущество inline
  • Забытый <noscript> fallback — пользователи без JS видят страницу без стилей
  • Critical CSS для всего сайта вместо per-page — включает ненужные стили
  • Устаревший critical CSS после изменений дизайна — регулярно обновлять в CI

Связанные темы

Ресурсы