Hint
Detect when elements enter the viewport — no scroll listener, no layout thrashing
// Lazy loading images
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // load real image
obs.unobserve(img); // stop watching this one
}
});
}, {
root: null, // null = viewport
rootMargin: '200px', // trigger 200px BEFORE element is visible
threshold: 0.1 // fire when 10% of element is visible
});
// Watch all lazy images
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
// Infinite scroll
const sentinel = document.querySelector('.load-more');
new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) loadNextPage();
}).observe(sentinel);
// entry properties:
// entry.isIntersecting — true/false
// entry.intersectionRatio — 0 to 1
// entry.boundingClientRect — element position
// entry.target — the observed element