Skip to Content
БраузерКритический путь отрисовки

Критический путь отрисовки

Уровень: middle.

Вопрос

Что браузер делает с HTML и CSS до первого кадра, и чем reflow отличается от repaint?

Короткий ответ

Браузер качает HTML, строит DOM, встречает CSS и JS. Стили без media, который сразу ложен, блокируют первую отрисовку: нужен CSSOM. Обычный скрипт без async и defer останавливает разбор HTML, пока файл не скачается и не выполнится. defer качается параллельно и выполняется после разбора документа, по порядку тегов. async выполнится, как только скачается, порядок между такими скриптами не гарантирован.

Дальше дерево рендера, раскладка (layout, reflow) и отрисовка (paint). Смена геометрии — ширина, шрифт, вставка узла — запускает layout. Смена цвета часто ограничивается paint. transform и opacity чаще не трогают layout и могут остаться на слое композитора.

Чтение offsetHeight сразу после записи стиля заставляет браузер посчитать layout синхронно. Чередование чтений и записей в цикле называется layout thrashing.

Разбор

Критический путь — ресурсы, без которых нельзя показать первый экран: HTML, блокирующий CSS, блокирующий JS. Картинка ниже сгиба и отложенный скрипт аналитики в него не входят.

document готов по DOMContentLoaded, когда разобран HTML и выполнены defer. load ждёт ещё стили, картинки и фреймы.

Слой для анимации создают осознанно. Бесконечный will-change: transform на всём списке держит лишнюю память. Свойство ставят на время анимации или не ставят, если и так анимируется transform.

На что смотрят на senior

Метрики, которые называют вслух: LCP (крупный контент), INP (отзывчивость на ввод), CLS (сдвиги вёрстки). Картинка без размера и шрифт без запасного метрического начертания двигают макет. Длинная задача в JS дольше примерно 50 мс бьёт по INP, даже если кадры скролла гладкие.

Принудительный синхронный layout виден в Performance: фиолетовые пересчёты между чтением геометрии и сменой класса. Лечение — прочитать геометрию пачкой, потом записать стили пачкой.

Типичные ошибки

  • Ставить скрипт в head без defer и блокировать разбор.
  • Читать offsetWidth внутри цикла по сотне элементов.
  • Анимировать top и left там, где хватает transform.
  • Путать первый кадр и load: пользователь видит страницу раньше, чем сработало load.

Задача

Скрипт подключён в head тремя способами по очереди: без атрибутов, с defer, с async. Какой из них точно выполнится до разбора всего HTML?

Показать ответ

Без атрибутов. Браузер останавливает парсер, пока скрипт не скачается и не выполнится.

defer выполняется после того, как документ разобран, сохраняя порядок таких скриптов. async выполнится сразу после загрузки и может попасть и до, и после конца HTML: порядок не гарантирован.

Last updated on