Animate with intersection observer

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

JS:
/* Intersection observer */
const animateWrapper = useRef(null)

useEffect(() => {
  if (!animateWrapper.current) return
  const animateContainers = animateWrapper.current.querySelectorAll('[data-animate]')
  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')
          }
        })
      },
      {
        // Options
        threshold: 0.5,
      },
    )

    // Initiate observation
    const observeTimeout = setTimeout(() => {
      observer.observe(container)
    }, 500)

    return () => {
      clearTimeout(observeTimeout)
      observer.unobserve(container)
    }
  })
}, [animateWrapper])

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);
  }
}