IntersectionObserver
polyfillThis library polyfills the native IntersectionObserver
API in unsupporting browsers. See the API
documentation for usage information.
You can install the polyfill via npm or by downloading a zip of this repository:
npm install intersection-observer
The examples below show various ways to add the
IntersectionObserver
polyfill to your site. Be sure to
include the polyfill prior to referencing it anywhere in your JavaScript
code.
Using <script>
tags in the
HTML:
<!-- Load the polyfill first. -->
<script src="path/to/intersection-observer.js"></script>
<!-- Load all other JavaScript. -->
<script src="app.js"></script>
Using a module loader (e.g. Browserify or Webpack):
// Require the polyfill before requiring any other modules.
require('intersection-observer');
require('./foo.js');
require('./bar.js');
It’s impossible to handle all possible ways a target element could intersect with a root element without resorting to constantly polling the document for intersection changes.
To avoid this extra work and performance penalty, the default
configuration of the polyfill optimizes for the most common
IntersectionObserver
use cases, which primarily include
target elements intersecting with a root element due to:
All of the above can be handled without polling the DOM.
There are, however, additional use cases that the default configuration will not detect. These include target elements intersecting with a root element due to:
:hover
, :active
, or
:focus
states.<textarea>
elements that cause other
elements to move around.If you need to handle any of these use-cases, you can configure the
polyfill to poll the document by setting the POLL_INTERVAL
property. This can be set either globally or on a per-instance
basis.
Enabling polling for all instance:
To enable polling for all instance, set a value for
POLL_INTERVAL
on the IntersectionObserver
prototype:
.prototype.POLL_INTERVAL = 100; // Time in milliseconds. IntersectionObserver
Enabling polling for individual instance:
To enable polling on only specific instances, set a
POLL_INTERVAL
value on the instance itself:
var io = new IntersectionObserver(callback);
.POLL_INTERVAL = 100; // Time in milliseconds.
io.observe(someTargetElement); io
Note: the POLL_INTERVAL
property must
be set prior to calling the .observe
method, or the default
configuration will be used.
Ignoring DOM changes
You can also choose to not check for intersections when the DOM
changes by setting an observer’s USE_MUTATION_OBSERVER
property to false
(either globally on the prototype or
per-instance)
.prototype.USE_MUTATION_OBSERVER = false; // Globally
IntersectionObserver
// for an instance
var io = new IntersectionObserver(callback);
.USE_MUTATION_OBSERVER = false; io
This is recommended in cases where the DOM will update frequently but you know those updates will have no affect on the position or your target elements.
Same-origin iframes are supported by the polyfill out of the box.
Additional code and configuration are required to support cross-origin iframes, both on the iframe and host sides.
The setup is as following:
_setupCrossOriginUpdater()
method. It will call the
provided callback whenever it receives the intersection data from the
the parent via messaging.A hypothetical host code:
function forwardIntersectionToIframe(iframe) {
createMessagingChannel(iframe, function(port) {
var io = new IntersectionObserver(function() {
.postMessage({
portboundingClientRect: serialize(boundingClientRect),
intersectionRect: serialize(intersectionRect)
;
}), {threshold: [0, 0.1, ..., 1]});
}.observe(iframe);
io;
}) }
Notice that the host should provide a threshold
argument
for the desired level of precision. Otherwise, the iframe side may not
update as frequently as desired.
A hypothetical iframe code:
createMessagingChannel(parent, function(port) {
if (IntersectionObserver._setupCrossOriginUpdater) {
var crossOriginUpdater = IntersectionObserver._setupCrossOriginUpdater();
.onmessage = function(event) {
portcrossOriginUpdater(
deserialize(event.data.boundingClientRect),
deserialize(event.data.intersectionRect)
;
);
}
}; })
This polyfill does not support the proposed v2 additions, as these features are not currently possible to do with JavaScript and existing web APIs.
The polyfill has been tested and known to work in the latest version of all browsers.
Legacy support is also possible in very old browsers by including a
shim for ES5 as well as the window.getComputedStyle
method.
The easiest way to load the IntersectionObserver polyfill and have it
work in the widest range of browsers is via polyfill.io, which will
automatically include dependencies where necessary:
<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>
With these polyfills, IntersectionObserver
has been
tested an known to work in the following browsers:
✔ |
✔ |
6+ |
✔ |
7+ |
✔ |
4.4+ |
To run the test suite for the IntersectionObserver
polyfill, open the intersection-observer-test.html
page in the browser of your choice.
If you run the tests in a browser that support
IntersectionObserver
natively, the tests will be run
against the native implementation. If it doesn’t the tests will be run
against the polyfill.