Animate with intersection observer

Random 1
Random 2
Random 3
Random 4
View code
HTML:
<div data-animate="bottom">
  <img src="https://picsum.photos/600/400?random=1" alt="Image 1" />
</div>

<div data-animate="top">
  <img src="https://picsum.photos/600/400?random=2" alt="Image 2" />
</div>

<div data-animate="left">
  <img src="https://picsum.photos/600/400?random=3" alt="Image 3" />
</div>

<div data-animate="right">
  <img src="https://picsum.photos/600/400?random=4" alt="Image 4" />
</div>

JS:
/* Intersection observer */
const animateContainers = document.querySelectorAll("[data-animate]");

if(animateContainers) {
  animateContainers.forEach((container) => {
    const observer = new IntersectionObserver(elements => {
      elements.forEach(el => {
        if(el.isIntersecting) {
          // Do stuff here when element is intersecting
          el.target.classList.add("animate")

          // Unobserve if it should be triggered only once
          observer.unobserve(container);
        }
      })
    },
    {
      // Options
      threshold: 0.5
    });

    // Initiate observation
    observer.observe(container);
  })
}

CSS:
[data-animate] {
  opacity: 0;
}

[data-animate="bottom"].animate {
  animation: 1s slideInFromBottom forwards;
}

[data-animate="right"].animate {
  animation: 1s slideInFromRight forwards;
}

[data-animate="left"].animate {
  animation: 1s slideInFromLeft forwards;
}

[data-animate="top"].animate {
  animation: 1s slideInFromTop forwards;
}

@keyframes slideInFromBottom {
  from {
    opacity: 0;
    transform: translateY(100px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideInFromTop {
  from {
    opacity: 0;
    transform: translateY(-100px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideInFromRight {
  from {
    opacity: 0;
    transform: translateX(100px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes slideInFromLeft {
  from {
    opacity: 0;
    transform: translateX(-100px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}