<div class="container">
    <div class="wrapper">
      <img class="imgA" src="https://ljc-dev.github.io/hosted-assets/thumb-a.png" alt="avatar a">
    </div>
    <div class="wrapper">
      <img class="imgB" src="https://ljc-dev.github.io/hosted-assets/thumb-b.png" alt="avatar b">
    </div>
    <div class="wrapper">
      <img class="imgC" src="https://ljc-dev.github.io/hosted-assets/thumb-c.png" alt="avatar c">
    </div>
    <div class="wrapper">
      <img class="imgD" src="https://ljc-dev.github.io/hosted-assets/thumb-d.png" alt="avatar d">
    </div>
  </div>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  width: 100%;
}

html {
  scroll-behavior: smooth;
}

.container {
  width: 100%;
  height: 100vh;
  overflow-x: hidden;
  overflow-y: auto;
  padding-top: 12rem;
}

.wrapper {
  position: relative;
  margin: 5rem auto;
  width: 400px;
  height: 400px;
}

img {
  position: absolute;
  top: 0;
  left: 0;
  height: 400px;
  opacity: 0;
  width: 400px;
  transition: all 1s;
}

.imgA {
  transform: translateX(-200px);
  opacity: 0;
}

.imgB {
  transform: translateX(200px);
  opacity: 0;
}

.imgC {
    transform: translateY(200px);
  opacity: 0;
}

.imgD {
  transform: scale(0);
}

.fadeInLeft {
  transform: translateX(0px);
  opacity: 1;
}

.fadeInRight {
  transform: translateX(0px);
  opacity: 1;
}

.fadeInBtm {
  transform: translateY(0px);
  opacity: 1;
}

.zoomIn {
  transform: scale(1);
  opacity: 1;
}
const container = document.querySelector(".container")
const wrappers = document.querySelectorAll(".wrapper")
const imgs = document.querySelectorAll("img")
const animClasses = [
  "fadeInLeft",
  "fadeInRight",
  "fadeInBtm",
  "zoomIn",
]
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    const currentIndex = Array.from(wrappers).indexOf(entry.target)
    if (entry.isIntersecting) {
      imgs[currentIndex].classList.add(animClasses[currentIndex])
    } else {
      if (entry.boundingClientRect.y > 0) {
        imgs[currentIndex].classList.remove(animClasses[currentIndex])
      }
    }
  })
}, {
  root: container,
  threshold: 0.1,
})


wrappers.forEach(wrapper => {
  observer.observe(wrapper)
})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.