I am running into a problem where my intersection observer has two entries both of whose targets are identical but their intersectionRatio is different at the same time in the app. Why could this be? Since it's the same element and the same viewport, shouldn't the intersectionRatio be the same? I am scrolling continuously in the app using .scrollTo(). Is it possible that the element is temporarily removed from the DOM and put back in which is resulting in the two entries?
I am using the IntersectionObserver as:
const intersectionObserverOptions = {
root: rootRef.current,
rootMargin: '0px',
threshold: 0.01
};
const observer = new IntersectionObserver(
intersectionObserverCallback,
intersectionObserverOptions
);
observer.observe(myElement);

When using the IntersectionObserver API, it is possible for two entries for the same element to have different
intersectionRatiovalues if the observations were recorded at different times during continuous scrolling. If the element is only partially visible at the first observation and fully visible at the next, you will see different ratios.I tried this CodePen to simulate that:
I get in the console:
The varying
Intersection Ratiovalues logged in the console demonstrate the intersection observer's behavior as an element is scrolled into and out of view: the intersection ratio for a single target element can indeed change over time, depending on its position relative to the viewport.That would confirm that:
Intersection Ratiocan change dynamically as an element enters or exits the viewport.entries[0].target === entries[1].targetcomparison would returntrue, confirming that it is indeed the same element being observed.Possible reasons:
The
IntersectionObserverexecutes its callbacks asynchronously. The browser may batch multiple visibility changes into separate callbacks if these changes occur in rapid succession, like during a scroll.If the observed element or its children are dynamically changing size, being styled, or if other DOM elements are affecting its layout during the scroll, the observer might fire callbacks with differing visibility states.
While the page is continuously scrolling (like with the
.scrollTo()method), the element's visibility can change multiple times. Each time it crosses the defined threshold, the observer invokes the callback, resulting in a sequence of entries showing the element's transition from invisible to fully visible and back to invisible.To address your question directly: even though it seems like the element's visibility in the DOM should be a binary state, the
IntersectionObserveris sensitive to the precise moment the observation is made. If the element is in the process of crossing the threshold at the time of observation, the callback might be triggered with anintersectionRatioof0(not visible) or1(fully visible), or any value in between. The element doesn't have to be removed or added to the DOM for this to happen; it just needs to cross the threshold between being in and out of view.