I am trying to invoke a callback via intersection observer.
I want the target
to be style: "position: fixed"
and move it via
style.top
.
I also specified the root element which is an ancestor of the target with style: "position: relative"
.
But when the target and the observer intersects, the callback function won't be triggered.
Are there some limitations I missed?
Here is what I typed:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>IO</title>
</head>
<body>
<div style="height: 200px;width: 100%;background: violet" class="upper">aaa</div>
<div style="position:relative;height: 200px;width: 100%;background: blueviolet" id="middle">bbb
<div id="target" style="position:fixed;top: 0px;width: 50px;height: 50px;background: firebrick">ccc</div>
</div>
<script>
let options = {
root: document.getElementById("middle"),
rootMargin: '0px',
threshold: 0
};
let observer = new IntersectionObserver(entry => {
console.log("observer's acting.")
}, options);
let target = document.getElementById("target");
observer.observe(target);
let stepping = 0;
let cb = () => {
target.style.top = stepping + 'px';
stepping += 4;
if (stepping < 300){
setTimeout(cb, 100);
}
};
window.addEventListener("click", () => {
cb();
})
</script>
</body>
</html>
And here is a codepen demo: codepen demo
You can click anywhere in the page to start moving the ccc
block.
The Intersection Observer API lets code register a callback function that is executed whenever an element they wish to monitor enters or exits another element (or the viewport), or when the amount by which the two intersect changes by a requested amount.
The IntersectionObserver method observe() adds an element to the set of target elements being watched by the IntersectionObserver . One observer has one set of thresholds and one root, but can watch multiple target elements for visibility changes in keeping with those.
The IntersectionObserver interface's read-only rootMargin property is a string with syntax similar to that of the CSS margin property. Each side of the rectangle represented by rootMargin is added to the corresponding side in the root element's bounding box before the intersection test is performed.
Intersection Observer can be considered more performant than listening for scroll events on the main thread, as it is asynchronous, and the callback will only fire when the element we're observing meets the specified threshold, instead every time the scroll position is updated.
Elements with position: fixed
are positioned relative to the viewport and the viewport moves. So, fixed positioned elements "move" as you scroll. Even though #target
is a child of #middle
, I believe the IntersectionObserver, with whatever it uses under the hood to calculate if the target
is entering/leaving the root
, never fires the callback because the target
is outside of the document flow.
Here is a related issue. There isn't much out in the interwebs related to this issue: https://bugs.chromium.org/p/chromium/issues/detail?id=653240
Note: Setting position: absolute
on the target does indeed fire the callback when entering and leaving the viewport.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With