4

Trying to understand a quirk in intersectionObserver API.

If an observed element is partially on screen but has not met the threshold defined in the options I would expect the call back not to fire, but it does. Trying to understand why or how to prevent it on page load.

function handleIntersect(entries, observer) {
  entries.forEach(function(entry) {
    if (entry.isIntersecting) {
      // Should only fire at >= 0.8
      console.log(entry, entry.intersectionRatio);
      entry.target.classList.add('play');
    }
  });
}

function createObserver(element) {
  let observer;

  const options = {
    threshold: [0.8]
  };

  observer = new IntersectionObserver(handleIntersect, options);
  observer.observe(element);
}

const waypoints = document.querySelectorAll('.section');

waypoints.forEach(waypoint => {
  createObserver(waypoint); 
});

Reduced test case: https://codepen.io/WithAnEs/pen/gxZPMK

Notice how the first 2 sections are animated in even though the second section does not meet the 0.8 threshold (console log). The first inclination is to add an intersectionRatio > 0.8 check, but this is a duplicate effort. Also, the ratio reporting is delayed so could be inaccurate enough not to pass this check.

1 Answers1

2

isIntersecting doesn't depend on thresholds. It is true, if target element touches or intersects root element. So it's always true if intersectionRatio > 0.

If an observed element is partially on screen but has not met the threshold defined in the options I would expect the call back not to fire, but it does.

Generally, callback is called when condition intersectionRatio >= your_threshold is changed. Therefore it can be called with any intersectionRatio value.

Moreover, it's always called initially.

Also pay attention that 0.8 is just your desired threshold, but observer.thresholds[0] is actual. Without going into details, they could be different a bit, e.g. in Chrome.

dizel3d
  • 3,619
  • 1
  • 22
  • 35
  • No I understand the isIntersecting property. I added the isIntersecting check to prevent every instance of intersection observer from firing st page load. The issue I’m having is preventing the initial page load from firing for elements outside the predefined threshold. I could add a check for percentage visible, but that seems strange considering the threshold is defined. –  Sep 30 '17 at 01:25
  • Updated the answer – dizel3d Oct 01 '17 at 18:37
  • Note that Chrome's implementation of `isIntersecting` differs from other browsers. It seems it is not spec compliant, meaning it may be `false` when `intersectionRatio > 0`. Bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=925643 – Oliver Joseph Ash Jul 15 '20 at 14:17