Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IntersectionObserver rootMargin ignored within iframe #283

Closed
zzebastien opened this issue Feb 3, 2018 · 9 comments
Closed

IntersectionObserver rootMargin ignored within iframe #283

zzebastien opened this issue Feb 3, 2018 · 9 comments

Comments

@zzebastien
Copy link

Hi,

I'm using the IntersectionObserver API within an iframe (same-origin policy) and have an issue with the 'rootMargin' option that is ignored when using 'root: null'.

I have a CodePen that demonstrate the issue, you'll see that the rootMargin set to 50px is ignored.

https://codepen.io/anon/pen/RQrBEW

The exact same code without an iframe works perfectly, so I'm wondering if this is a limitation of the API when using an iframe?

Just scroll-down in the CodePen and check the debug information on the right of the page that is displaying the result of the Intersection Observer callback.

The Intersection Observer callback is triggered as soon as "1px" of each ".component" div .isIntersecting value change, i.e. the rootMargin (here 50px) is IGNORED.

Bug is reproducible on Chrome 64.0.3282.140 (MacOS).

Note: I do NOT want to use anything else that "root: null" (or "root: document.querySelector('body')") in this scenario because I do not have any control on the content of the iframe in my application.
I know that this issue could be solved by setting the "root" value to an ancestor (div) of the components I'm observing, but as I said I cannot control the content of the iframe and could only rely on root: body or root: null.

Thanks for your time!
:)
Seb

@zzebastien
Copy link
Author

duplicate of #183

@szager-chromium
Copy link
Collaborator

This is working as intended:

https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-rootmargin

Root margin is never applied when the target is in a different frame from the root, regardless of origin policy. If I remember correctly, we did this because there was a desire to keep cross-frame observations as simple as possible.

@Rendez
Copy link

Rendez commented May 14, 2018

@szager-chromium Correct me if I'm wrong... I got really confused about this earlier because it seems like negative root margins do get applied.

I haven't published an example yet, but I've tested on this one on my machine – changing it to rootMargin=-50px 0px – and then I get only negative root margins being applied within the iframe. Now, the same example outside its iframe works with negative and positive root margins as normal.

However, with the polyfill applied (same link on Safari), seems like both negative and positive root margins are applied within iframes and outside them, which makes things yet more inconsistent.

If you need it, I'll create a sandboxed example to demonstrate any of the statements above, just waiting for your clarification on this first.

@szager-chromium
Copy link
Collaborator

@Rendez That's a localhost link you provided in your comment, so I can't see it.

rootMargin should be applied consistently regardless of whether the value is negative or positive. The spec language seems clear enough to me, but let me know if you think it could be clarified or improved.

If you think that a particular browser implementation is doing it wrong, then I would ask that you please file a bug in the browser's bug tracker. If you think that the polyfill is incorrect, then please file a separate bug here against the polyfill implementation.

@Rendez
Copy link

Rendez commented May 15, 2018

@szager-chromium apologies. I just corrected it. Ok, so then I will file the corresponding bugs with examples.

@Rendez
Copy link

Rendez commented May 15, 2018

@szager-chromium I've added a new "Playground" section to the storybook.

The box within the viewport has a height 120px, and you can switch in the Knobs section between rootMargin 0px, 60px, -60px, and 120px.

The default value is 60px, to demonstrate that the entry should contain: {isIntersecting: true, intersectionRatio: 0} on the initial event. If you open the example's iframe link in a separate tab, so that the viewport is the parent Window, 60px as default will always apply, and there you'll see that isIntersecting is actually true as expected.

Chrome and Firefox do not consider this an intersection within the iframe whereas Safari (with the polyfill) and Edge16 (without the polyfill) do.

@szager-chromium
Copy link
Collaborator

Looking at this issue again, I see that I gave a completely bogus answer to the initial question. It's NOT true that root margin is only applied for the same-document case (and the spec doesn't say that). Root margin will be applied in the same-origin cross-document case (i.e., target element inside a same-origin iframe, and observer using the implicit root).

However, the root margin is only applied to the top-level container, which in the case of the implicit root is the scrolling viewport of the top-level document. The iframe element is also a clipping container, and the root margin is NOT applied when computing clipping from the iframe element's boundary.

If you want the root margin to apply to the iframe element's boundary, then you'll have to use an observer with an explicit root, which should be document.scrollingElement within the iframe. If you also need to compute intersection with the top-level viewport (the implicit root), that will require a second observer.

@phocks
Copy link

phocks commented Jun 16, 2020

Looks like a fix was integrated and so I've managed to get mine working by setting document as the root

observer = new IntersectionObserver(doObserved, {
      root: document,
      rootMargin: `${window.innerHeight * 0.6}px 0px`,
      threshold: 0.0
    });

#372

@NickCiliak
Copy link

If you're okay with adding extra markup and css for the purpose of getting your Intersection Observer to work the way you expect in a CodePen, this is the only way that has actually worked for me, despite trying everything in this thread: https://codepen.io/nickcil/pen/MWbqOaJ

I wrapped my HTML in a full width and height element that is set to position: fixed and overflow: auto. Then I set that element as the root for the observer. rootMargin now works as expected in the pen.

phelipetls added a commit to phelipetls/blog that referenced this issue Apr 30, 2022
The setup before was over complicated, because I tried to use
IntersectionObserver to check if navbar was intersecting with the main
element before styling it with a border etc.

This kind of worked, but it broke testing with Cypress because the
website was rendered inside an iframe, which the IntersectionObserver
API has issues when using implicit root and rootMargin, see
w3c/IntersectionObserver#283 (comment)
for details.

Now, I simplified it to get rid of IntersectionObserver. Now, the border
is applied when we detect that the page scroll is greater than the
navbar height.

Also, the navbar will get hidden every time the user scrolls down,
regardless of where in the page (before this commit, this only happened
after the top of the viewport intersected with the main element).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants