Lazy loading images with Intersection Observer

An easy example on how to use Intersection Observer API to lazy load images.

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<div class="container">
  <div>
    <div class="col-12">
      <img src="https://www.fillmurray.com/150/200" class="lazy" loading="lazy">
    </div>
    <div class="col-12">
      <img src="https://www.fillmurray.com/160/200" class="lazy" loading="lazy">
    </div>
    <div class="col-12">
      <img src="https://www.fillmurray.com/170/200" class="lazy" loading="lazy">
    </div>
    <div class="col-12">
      <img src="https://www.fillmurray.com/180/200" class="lazy" loading="lazy">
    </div>
    <div class="col-12">
      <img src="https://www.fillmurray.com/190/200" class="lazy" loading="lazy">
    </div>
    <div class="col-12">
      <img src="https://www.fillmurray.com/200/200" class="lazy" loading="lazy"> 
    </div>
  </div>
</div>

CSS

.lazy {
  opacity: 0;
  width: 100%;
  min-height: 200px;
  margin-top: 200px;
  object-fit: cover;
  -webkit-transition: opacity 2s ease-in;
       -moz-transition: opacity 2s ease-in;
        -ms-transition: opacity 2s ease-in;
         -o-transition: opacity 2s ease-in;
            transition: opacity 2s ease-in;
}

.lazy.loaded {
  opacity: 1;
}

JavaScript

const imgLoaded = ( ev ) => {
	console.log("loaded: ", ev.target.src )
  ev.target.classList.add('loaded')
}

document.addEventListener('DOMContentLoaded', (event) => {
  const imgs = document.querySelectorAll('img')
  Array.from(imgs).forEach((img)=>{
  	img.addEventListener('load', imgLoaded)
  })
});