IntersectObserver

by rough cheap

HTML

<div class="obox">
  <div class="vertical">
    Welcome to <strong>The Box1!</strong>
  </div>
</div>
<div class="obox">
  <div class="vertical">
    Welcome to <strong>The Box1!</strong>
  </div>
</div>
<div class="obox">
  <div class="vertical">
    Welcome to <strong>The Box1!</strong>
  </div>
</div>

CSS

.obox {
  background-color: rgba(40, 40, 190, 255);
  border: 4px solid rgb(29, 29, 120);
  transition: background-color 1s, border 1s;
  width: 350px;
  height: 350px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  margin-top: 1000px;
  margin-bottom: 1000px;
}

.vertical {
  color: white;
  font: 16px "Arial";
}

.extra {
  width: 350px;
  height: 350px;
  margin-top: 10px;
  border: 4px solid rgb(29, 29, 120);
  text-align: center;
  padding: 20px;
}

JavaScript

(function() {
	let boxElements;
  let observers = [];
  let prevRatios = {};
  
  window.addEventListener('load', (e) => {
  	boxElements = document.getElementsByClassName('obox');
    createObserver();
  }, false);
  
  function createObserver() {
  	let observer;
    let options = {
    	root: null,
      rootMargin: '0px',
      threshold: buildThresholdList(20)
    };
    
    for (let i = 0; i < boxElements.length; i++) {
    	boxElements.item(i).id = `obox-${i}`, prevRatios[boxElements.item(i).id] = 0.0;
    	observers[i] = new IntersectionObserver(intersectionHandler, options);
      observers[i].observe(boxElements.item(i));
    }
  }
  
  function buildThresholdList(numSteps) {
    let thresholds = [];
    for (let i = 1.0; i <= numSteps; i++) {
      let ratio = i / numSteps;
      thresholds.push(ratio);
    }
    thresholds.push(0);
    return thresholds;
  }
  
  function intersectionHandler(entries, observer) {
    entries.forEach((entry) => {
    	let ratio = entry.intersectionRatio;
      let prevRatio = prevRatios[entry.target.id];
      entry.target.children[0].innerHTML = `Prev: ${prevRatio}<br> Current: ${ratio}`;
      prevRatios[entry.target.id] = ratio;
    });
  }
})();