Примусовий синхронний layout: читання геометрії після запису в DOM
Що відбувається
Зазвичай layout відбувається після завершення JavaScript, один раз за кадр. Але якщо ви змінили DOM і одразу читаєте layout-властивість — offsetWidth, scrollHeight, getBoundingClientRect(), getComputedStyle() — браузер зобов'язаний зупинитися й порахувати макет прямо тут, синхронно, усередині вашої задачі, бо відповідь залежить від вашої незбереженої зміни.
Один примусовий layout дешевий на маленькій сторінці. На великому DOM або в циклі (що перетворюється на layout thrashing) він додає обробнику сотні мілісекунд.
Як розпізнати
- Довгий processing time у розбивці INP, при цьому в DevTools Performance блоки Layout вкладені всередину скриптової задачі (попередження «Forced reflow»).
- Long Animation Frames API показує великий forcedStyleAndLayoutDuration у вашого скрипта.
- Обробник одночасно змінює DOM і вимірює елементи.
Як виправити
- Читайте всю геометрію до першого запису в DOM усередині задачі.
- Кешуйте вимірювання, які не змінюються (розміри елементів, ширину контейнера), замість повторного читання на кожну подію.
- Якщо виміряти після зміни необхідно — відкладіть читання до requestAnimationFrame наступного кадру або використовуйте ResizeObserver / IntersectionObserver замість опитування геометрії.
Проблема
grid.style.width = next + "px" // write: layout is now dirty
const rect = cell.getBoundingClientRect() // read → forced synchronous layout
Виправлення
const rect = cell.getBoundingClientRect() // read first, layout is clean
grid.style.width = next + "px" // write after; browser lays out
// once, before the next paint
Просканувати свій сайт безкоштовно →