Старий спосіб дізнатися, чи елемент з'явився на екрані, - обробник scroll з getBoundingClientRect() для кожного елемента. Він спрацьовує десятки разів на секунду, виконується в головному потоці й примушує браузер рахувати layout - звідси «смикання» прокрутки.
IntersectionObserver повідомляє, коли елемент перетинає область видимості (або інший елемент-контейнер). Обчислення виконує браузер, асинхронно, без примусового layout.
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (!entry.isIntersecting) continue;
const img = entry.target;
img.src = img.dataset.src; // завантажити зображення
observer.unobserve(img); // більше не стежити
}
}, { rootMargin: '200px' }); // почати трохи заздалегідь
document.querySelectorAll('img[data-src]').forEach((img) => observer.observe(img));
Типові застосування:
- Нескінченний скрол: спостерігати за «маркером» наприкінці списку й підвантажувати наступну сторінку, коли він стає видимим.
- Аналітика переглядів: реклама чи блок вважається показаним, коли видно 50% протягом секунди (
threshold: 0.5). - Анімації при появі, пауза відео поза екраном.
Що варто знати:
- Для простих зображень лінивого завантаження вже вбудовано:
<img loading="lazy">. Спостерігач потрібен для складніших випадків. thresholdзадає, яку частку елемента має бути видно;rootMargin- розширює чи звужує область перевірки.- Спостерігача треба відключати (
disconnect()), коли компонент знищено, інакше він триматиме посилання на елементи. - Для зміни розміру елементів є споріднений
ResizeObserver.