Главная идея
Браузер тратит время на две вещи: скачать ресурсы (HTML, CSS, шрифты, картинки) и отрисовать их на экране. Оптимизация производительности — это уменьшить и то, и другое: передать по сети меньше байтов и заставить браузер пересчитывать раскладку как можно реже. Цель не абстрактная «скорость», а конкретный пользовательский опыт: как быстро появляется контент, насколько он стабилен и как быстро реагирует на клики.
Оптимизация — это как собрать багаж перед дорогой. Берёшь только нужное (минификация, удаление неиспользуемого CSS), упаковываешь компактно (WebP вместо тяжёлого PNG), а вещи для первого дня кладёшь в ручную кладь, чтобы не ждать выдачи всего чемодана (Critical CSS для первого экрана). Чем легче багаж — тем быстрее ты в пути.
Как браузер рисует страницу (render pipeline)
Каждый раз, когда что-то меняется на странице, браузер проходит конвейер из четырёх этапов. Понимание этого конвейера — ключ к плавным анимациям.
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 мс.
Базовый CSS первого экрана
Так выглядит компактный Critical CSS: только то, что нужно для первого экрана, и анимации на дешёвом transform.
/* 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 */
}