I need to know out when dozens of HTMLElements are inside or outside of the viewport when scrolling down the page. So I'm using the IntersectionObserver API
to create several instances of a VisibilityHelper
class, each one with its own IntersectionObserver. With this helper class, I can detect when any HTMLElement is 50% visible or hidden:
Working demo:
// Create helper class
class VisibilityHelper {
constructor(htmlElem, hiddenCallback, visibleCallback) {
this.observer = new IntersectionObserver((entities) => {
const ratio = entities[0].intersectionRatio;
if (ratio <= 0.0) {
hiddenCallback();
} else if (ratio >= 0.5) {
visibleCallback();
}
}, {threshold: [0.0, 0.5]});
this.observer.observe(htmlElem);
}
}
// Get elements
const headerElem = document.getElementById("header");
const footerElem = document.getElementById("footer");
// Use helper class to know whether visible or hidden
const headerViz = new VisibilityHelper(
headerElem,
() => {console.log('header is hidden')},
() => {console.log('header is visible')},
);
const footerViz = new VisibilityHelper(
footerElem,
() => {console.log('footer is hidden')},
() => {console.log('footer is visible')},
);
#page {
width: 100%;
height: 1500px;
position: relative;
background: linear-gradient(#000, #fff);
}
#header {
position: absolute;
top: 0;
width: 100%;
height: 100px;
background: #f90;
text-align: center;
}
#footer {
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background: #09f;
text-align: center;
}
<div id="page">
<div id="header">
Header
</div>
<div id="footer">
Footer
</div>
</div>
The problem is that my demo above creates one IntersectionObserver
for each HTMLElement that needs to be watched. I need to use this on 100 elements, and this question indicates that we should only use one IntersectionObserver
per page for performance reasons. Secondly, the API also suggests that one observer can be used to watch several elements, since the callback will give you a list of entries.
How would you use a single IntersectionObserver
to watch multiple htmlElements
and trigger unique hidden/visible callbacks for each element?