Перерасчёт компоновки

Оригинальное название: reflow

Коротко

Этап работы браузера, на котором он заново вычисляет размеры и координаты элементов страницы после изменений, влияющих на геометрию (reflow, или layout).

Что такое «Перерасчёт компоновки»

Чтобы показать страницу, браузер проходит несколько этапов: вычисляет стили, раскладывает элементы, рисует их и собирает слои в итоговую картинку. Раскладка — самый связанный этап: ширина одного блока влияет на перенос строк в нём, высота — на положение всего, что ниже. Поэтому изменение размеров одного элемента может заставить браузер пересчитать компоновку большой части страницы. На больших каталогах и сложных формах это уже заметные миллисекунды.

Что вызывает перерасчёт

  • Добавление и удаление элементов, изменение текста.
  • Изменение свойств геометрии: width, height, padding, margin, top, font-size, display.
  • Загрузка веб-шрифта или картинки без заданных размеров.
  • Изменение размеров окна и поворот телефона.
  • Чтение геометрии после изменения стилей. Свойства offsetHeight, clientWidth, scrollTop и метод getBoundingClientRect() требуют актуальных значений, и браузер выполняет раскладку немедленно, вне очереди.

Пример: лишние перерасчёты в цикле

// плохо: чтение и запись чередуются — раскладка на каждой итерации
cards.forEach(card => {
  card.style.height = card.offsetWidth * 0.75 + 'px';
});

// лучше: сначала все чтения, потом все записи
const widths = cards.map(card => card.offsetWidth);
cards.forEach((card, i) => {
  card.style.height = widths[i] * 0.75 + 'px';
});

В первом варианте браузер после каждой записи вынужден пересчитать раскладку, чтобы ответить на следующее чтение. Такое явление называют layout thrashing. Во втором варианте раскладка выполняется один раз. А в этой конкретной задаче скрипт вообще не нужен: пропорции карточки задаёт свойство aspect-ratio: 4 / 3.

Как найти и уменьшить

Во вкладке Performance инструментов разработчика перерасчёты видны как блоки Layout, а принудительные помечаются предупреждением Forced reflow со ссылкой на строку кода. Основные приёмы:

  • анимировать transform и opacity вместо размеров и позиций;
  • указывать width и height у картинок и резервировать место под баннеры, чтобы вёрстка не прыгала;
  • ограничивать область пересчёта свойством contain — см. изоляцию компоновки;
  • группировать изменения DOM и выполнять их в requestAnimationFrame.

После раскладки браузер обычно переходит к перерисовке, так что каждый лишний перерасчёт тянет за собой и её. Практический чек-лист по этим метрикам для одной из CMS — в статье об ускорении сайта на 1С-Битрикс.

Обновлено:

Все термины раздела «Frontend»

Что будем искать? Например,Продвижение