Intersection Observer

by Artem

HTML

<div class="grid-container">
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img src="https://placehold.it/960x540" /></div>
  <div class="grid-item"><img...

SCSS

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  grid-auto-rows: minmax(270px, 1fr);
  max-width: 1280px;
  margin: 0 auto;
}

.grid-row,
.grid-item {
  display: block;
  overflow: hidden;
}

.grid-item img {
  object-fit: cover;
  object-position: center;
  width: 100%;
  height: 100%;
}

.grid-item {
  transform: translateY(-10%);
  opacity: 0;
  transition: 600ms transform cubic-bezier(0.55, 0.055, 0.675, 0.19), 600ms opacity cubic-bezier(0.55, 0.055, 0.675, 0.19) 300ms;
  &.inview {
    transform: translateY(0);
    opacity: 1;
  }
}

JavaScript

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    const rand = Math.floor(Math.random() * 30);
    if (entry.isIntersecting === true) {
      const img = entry.target.querySelector("img");
      entry.target.classList.add("inview");
      img.src = `https://source.unsplash.com/random/960x540/?${rand}`;
    } else {
      entry.target.classList.remove("inview");
    }
  });
});
const items = document.querySelectorAll(".grid-item");

items.forEach((item, index) => {
  observer.observe(item, index);
});