Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intersection observer does not work with target with position: fixed

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.

like image 403
krave Avatar asked Mar 20 '18 16:03

krave


People also ask

How does intersection observer work?

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.

Can intersection observer observe multiple elements?

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.

What is rootMargin in intersection observer?

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.

Is intersection an observer performant?

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.


1 Answers

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.

like image 115
snewcomer Avatar answered Nov 15 '22 15:11

snewcomer