Lazy-load images with IntersectionObserver

const io = new IntersectionObserver((entries) => {
  entries.filter(e => e.isIntersecting).forEach(e => {
    e.target.src = e.target.dataset.src;
    io.unobserve(e.target);
  });
});

document.querySelectorAll('img[data-src]').forEach(img => io.observe(img));