Урок 49. Теория: Оптимизация и производительность

📁 Раздел: Качество вёрстки ⏱️ Время изучения: ~85 мин 🎯 Сложность: Продвинутая
#loading #picture #font-display #will-change

⚡ Кратко

Производительность сайта — это про то, насколько быстро пользователь видит и может пользоваться страницей. Главные рычаги:

  • Меньше байтов: минификация CSS, удаление неиспользуемых правил (PurgeCSS), оптимизация картинок (WebP/AVIF, loading="lazy").
  • Быстрее первый экран: Critical CSS встроен в <head>, шрифты с font-display: swap.
  • Плавные анимации: анимируем transform и opacity (дёшево, GPU), а не width/top (дорого, reflow).
  • Сначала измеряем: Lighthouse и Core Web Vitals (LCP, CLS, INP) — потом оптимизируем.

Главная идея

Браузер тратит время на две вещи: скачать ресурсы (HTML, CSS, шрифты, картинки) и отрисовать их на экране. Оптимизация производительности — это уменьшить и то, и другое: передать по сети меньше байтов и заставить браузер пересчитывать раскладку как можно реже. Цель не абстрактная «скорость», а конкретный пользовательский опыт: как быстро появляется контент, насколько он стабилен и как быстро реагирует на клики.

Оптимизация — это как собрать багаж перед дорогой. Берёшь только нужное (минификация, удаление неиспользуемого CSS), упаковываешь компактно (WebP вместо тяжёлого PNG), а вещи для первого дня кладёшь в ручную кладь, чтобы не ждать выдачи всего чемодана (Critical CSS для первого экрана). Чем легче багаж — тем быстрее ты в пути.

Как браузер рисует страницу (render pipeline)

Каждый раз, когда что-то меняется на странице, браузер проходит конвейер из четырёх этапов. Понимание этого конвейера — ключ к плавным анимациям.

Style какие правила Layout размеры/позиции Paint пиксели, цвета Composite слои на GPU ⬅ изменишь width/top — пересчёт отсюда (дорого) transform/opacity — только отсюда (дёшево)
Чем правее этап, на котором браузер «вступает» в конвейер, тем дешевле изменение. transform и opacity работают на этапе Composite (GPU) и не трогают Layout/Paint.

Reflow и repaint — почему анимации тормозят

Reflow (перерасчёт раскладки) запускается, когда меняются геометрические свойства: width, height, top, left, margin, padding. Браузер заново вычисляет позиции элементов — потенциально всей страницы. Repaint (перерисовка) дешевле: запускается при смене color, background, box-shadow — геометрия не меняется, но пиксели перерисовываются.

Reflow — это как пересчёт всей раскладки на полках в магазине, когда ты сдвинул одну коробку: соседние товары едут, ценники переклеиваются, кладовщик пересчитывает места. Repaint — это просто перекрасить одну коробку, не двигая остальные. А transform — это передвинуть коробку на отдельной тележке, не трогая полку вообще.

Поэтому для анимаций используют transform (сдвиг, масштаб, поворот) и opacity (прозрачность): они обрабатываются композитором на GPU и не вызывают ни reflow, ни repaint основного слоя. Это связь с уроками 42–43 про анимации и переходы.

Когда применять и частая ошибка

Оптимизируй после измерения, а не «на всякий случай». Сначала открой Lighthouse (вкладка в DevTools) или панель Performance, найди реальное узкое место, и только потом меняй код. will-change: transform подсказывает браузеру заранее вынести элемент на отдельный слой — но это инструмент точечный: повесишь его на десятки элементов «про запас» — съешь память и сделаешь хуже.

Частая ошибка: анимировать width, height, top/left ради «красоты» — каждая такая анимация дёргает reflow на каждом кадре и роняет FPS. Замени на transform: scale() / translate().

Метрики: Core Web Vitals

  • LCP (Largest Contentful Paint) — за сколько появляется самый крупный элемент первого экрана. Цель: < 2.5 с.
  • CLS (Cumulative Layout Shift) — насколько «прыгает» вёрстка при загрузке. Цель: < 0.1. Лечится явными размерами картинок (width/height) и font-display.
  • INP (Interaction to Next Paint) — задержка отклика на действие пользователя. Цель: < 200 мс.
⚠️ Проверить по документации: точные пороговые значения Core Web Vitals и формулы расчёта Google периодически пересматривает — сверяйтесь с web.dev/vitals перед сдачей проекта.

Базовый CSS первого экрана

Так выглядит компактный Critical CSS: только то, что нужно для первого экрана, и анимации на дешёвом transform.

📄 lesson-49/styles.css
/* Critical CSS: first screen */
.hero {
  width: min(100% - 2rem, 72rem);
  min-height: 70svh;
  margin-inline: auto;
  padding-block: clamp(3rem, 8vw, 7rem);
}

.hero img {
  display: block;
  width: 100%;
  height: auto;       /* стабильная высота = нет CLS */
}

.card {
  transition: transform 180ms ease, opacity 180ms ease;
}

.card:hover {
  transform: translateY(-0.25rem);  /* дёшево: только composite */
}

Навигация