How to detect when an element becomes visible
Short answer
IntersectionObserver calls a function when observed elements enter or leave the visible area:
<style>
.box { height: 150px; margin: 400px 0; background: #ddd; transition: background 0.5s; }
.box.visible { background: #4caf50; }
</style>
<div class="box"></div>
<div class="box"></div>
<script>
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
entry.target.classList.toggle('visible', entry.isIntersecting);
}
});
document.querySelectorAll('.box').forEach((box) => observer.observe(box));
</script>Only once
For lazy loading, stop observing the element after the first appearance:
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src;
observer.unobserve(entry.target);
}
}
}, { rootMargin: '200px' });
document.querySelectorAll('img[data-src]').forEach((img) => observer.observe(img));Common mistake
For images there is a simpler way that needs no JavaScript at all: the attribute loading="lazy".
<img src="photo.jpg" loading="lazy" alt="Photo">