Щоб показати сторінку, браузер рахує layout (розміри й позиції елементів, у Firefox це називають reflow), а потім paint - малює пікселі, і composite - збирає шари.
- Reflow (layout) - перерахунок геометрії. Дорогий: зміна розміру одного елемента може зачепити батьків, сусідів і нащадків.
- Repaint - перемальовування без зміни геометрії (колір, тінь). Дешевше.
- Лише composite -
transformіopacityна окремому шарі: найдешевше, часто на GPU.
Layout thrashing - чергування записів і читань геометрії в циклі. Кожне читання (offsetHeight, getBoundingClientRect(), scrollTop) після запису змушує браузер синхронно перерахувати layout:
// Погано: N примусових перерахунків
for (const card of cards) {
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`; });
Інші правила:
- Анімувати
transformіopacity, а неtop,left,width,height. - Групувати зміни стилів через клас, а не десяток окремих присвоєнь
style. - Візуальні оновлення - у
requestAnimationFrame, щоб вони збігалися з кадром. content-visibility: autoдозволяє браузеру пропускати layout і paint для невидимих частин довгої сторінки.
Як знайти проблему: вкладка Performance у DevTools - фіолетові блоки «Layout» з попередженням «Forced reflow» показують рядок коду, що спричинив перерахунок.