HTML-element visibility check
One of the best known functions when it comes to turning effects on / off on elements which are not yet visible (for example only after a scroll). Javascript offers us an API that I personally find very simple and comfortable.
This is the IntersectionObserver API.
You might want to do this so that you can toggle images by the minute or because you need to know if the user is actually looking at a certain banner advertising. You can do this by plugging in the scrolling event or using a periodic timer and calling getBoundingClientRect () on that element.
This approach, however, is painfully slow because every call to getBoundingClientRect () forces the browser to redistribute the entire page and will introduce considerable junk on your website. Things are almost impossible when you know your site is loaded in an iframe and want to know when the user can see an item.
Single origin model and browser will not allow you to access to the data of the web page containing the iframe. This is a common problem for ads, for example, which are frequently used using iframes.
Make this visibility test more efficient, the IntersectionObserver API was designed, and it landed in Chrome 51. IntersectionObserver lets you know when an observed element enters or exits the browser window.
How to create an IntersectionObserver?
Let's see this code:
var io = new IntersectionObserver( entries => { console.log(entries); }, { /* Using default options. Details below */ } ); // Begin to observe element io.observe(element); // stop observing element // io.unobserve(element); // deactivate the IntersectionObserver // io.disconnect();
Using the default options for IntersectionObserver, the callback function will be called both when the element will appear partially and when it will leave the window completely.
If you want to observe several elements, it is advisable to observe several elements using the same IntersectionObserver instance by calling observe () multiple times.
An input parameter is passed to your callback. It's an array of objects IntersectionObserverEntry. Each object contains updated intersection data for one of your observed elements.
For more information see https://developers.google.com/web/updates/2016/04/intersectionobserver.
Now we will try to write a small example: we want to try to see when is the box number 10 would be visible and display the visible portions to the right at the top of the page.
Here is a complete example:
Our Html:
<div class="container"> <div id="info"></div> <header></header> <main class="content"> <div class="box">Box 1</div> <div class="box">Box 2</div> <div class="box">Box 3</div> <div class="box">Box 4</div> <div class="box">Box 5</div> <div class="box">Box 6</div> <div class="box">Box 7</div> <div class="box">Box 8</div> <div class="box">Box 9</div> <div id="mybox" class="box">Box 10</div> <div class="box">Box 11</div> <div class="box">Box 12</div> <div class="box">Box 13</div> <div class="box">Box 14</div> </main> <footer></footer> </div>
A bit of css ;-)
* { box-sizing: border-box; } .container { width: 80%; margin: 0 auto; border: 1px solid #000; display: grid; } header { height: 100px; background-color: yellow; } main { display: grid; grid-template-columns: repeat(3, 1fr); } .box { height: 200px; background-color: orange; margin: 10px; padding: 10px; color: #fff; text-align: center; } #mybox { border: 5px solid green; } #info { position: fixed; width: 50px; height: 20px; border: 2px solid red; right: 20px; font-wight: bold; text-align: center; } footer { height: 100px; background-color: cyan; }
and the JS
var io = new IntersectionObserver( entries => { let ratio = Math.round(parseFloat(entries[0].intersectionRatio.toString().substr(0, 4)) + "e+2"); document.getElementById('info').textContent = `${ratio}%`; }, { threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] } ); // Start observing an element io.observe(document.getElementById('mybox'));
I find this API really effective seeing the many times I tried to simulate this feature writing dozens of lines of Javascript and it really didn't work as it should.
This API works in FF, chrome and Edge from some versions. But the good news is that there is a polyfill (see https://github.com/que-etc/intersection-observer-polyfill).