JSFiddle - React, Tailwind, and code Playground
by tuanderful
HTML
<h3>Example of IntersectionObserver polyfill bug</h3>
<p>Occurs when using the intersectionObserver polyfill, and body has height of 100% and overflow-y: scroll.</p>
<p>Expected behavior: the callback should be called when the item scrolls in and out of view (when the threshold crosses 0).</p>
<p>Actual behavior: callback is called for #item1 when the threshold crosses 1. callback never called for #item2</p>
<em>Please see <a href="https://jsfiddle.net/tuanderful/a4zsv08p/6/" target="_blank">https://jsfiddle.net/tuanderful/a4zsv08p/6/</a> for an example of default behavior in Chrome.</em>
<div id="grid">
<div id="item1" class="gridItem" style="top: 0; left: 0">
When using the IntersectionObserver polyfill, slightly scrolling down causes the callback to be called (when the threshold crosses 1).
<br />Expected behavior: the callback should be called when the item scrolls out of view (when the threshold crosses 0).
</div>
<div id="item2" class="gridItem" style="top: 2000px; left: 0">
Expected behavior: the callback should be called when the item scrolls into view (threshold crosses 0).
<br />Actual behavior: the callback is never called.
</div>
</div>
CSS
body {
// Disabling overflow-y "fixes" the issues
height: 100%;
overflow-y: scroll;
}
#grid {
position: relative;
}
.gridItem {
width: 200px;
height: 300px;
background: rgba(0, 0, 204, .6);
position: absolute;
}
JavaScript
// Force the polyfill
delete window.IntersectionObserver;
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(window, document) {
'use strict';
// Exits early if all IntersectionObserver and IntersectionObserverEntry
// features are natively supported.
if ('IntersectionObserver' in window &&
'IntersectionObserverEntry' in window &&
'intersectionRatio' in window.IntersectionObserverEntry.prototype) {
return;
}
// Use :root element of the document for .contains() calls because older IEs
// support Node.prototype.contains only on Element nodes.
var docElement = document.documentElement;
/**
* An IntersectionObserver registry. This registry exists to hold a strong
* reference to IntersectionObserver instances currently observering a target
* element. Without this registry, instances without another reference may be
* garbage collected.
*/
var registry = [];
/**
* Creates the global IntersectionObserverEntry constructor.
* https://wicg.github.io/IntersectionObserver/#intersection-observer-entry
* @param {Object} entry A dictionary of instance properties.
* @constructor
*/
function IntersectionObserverEntry(entry) {
this.time = entry.time;
this.rootBounds = entry.rootBounds;
this.boundingClientRect = entry.boundingClientRect;
this.intersectionRect = entry.intersectionRect;
this.target = entry.target;
// Calculates the intersection ratio. Sets it to 0 if the...