JSFiddle - React, Tailwind, and code Playground

HTML

<div class="invisibility"></div>
<div class="container">
  
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

CSS

.container {
  height: 400px;
  width: 400px;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap;
  overflow-y: scroll;
}

.item {
  width: 200px;
  height: 120px;
  background: red;
  margin: 10px 0 0 0;
}

.invisibility {
  height: 20px;
  width: 100%;
  background: yellow;
  position: absolute;
  left: 0;
  top: 350px;
}

JavaScript

const container = document.querySelector('.container');

var options = {
    root: document.querySelector('.invisibility'),
    rootMargin: '0px',
    threshold: 1
}
var callback = function(entries, observer) {
      entries.forEach((entry, i) => {
      	console.log(i)
      	 if(entry) entry.target.style.background = 'green';
         
      });
};
var observer = new IntersectionObserver(callback, options);

container.querySelectorAll('.item').forEach(item => {
	observer.observe(item);
});