-
Notifications
You must be signed in to change notification settings - Fork 526
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
Incompatibilities between spec and implementations for observer events #222
Comments
In your first example, Chrome exhibits the behavior we would expect were this spec change applied.
"Let thresholdIndex be the index of the first entry in observer.thresholds whose value is greater than intersectionRatio, or the length of observer.thresholds if intersectionRatio is greater than OR EQUAL TO the last entry in observer.thresholds." In your second example, Chrome exhibits the behavior we would expect were this spec change applied. Thoughts? I think the first change ought to be non-controversial, but the second one is perhaps more debatable. |
One thing Edge's implementation seems to miss is an initial event being fired when starting to observe a non-intersecting element (see missing <isIntersecting: false, intersectionRatio: 0> events). See #165 for discussion on this and https://github.com/WICG/IntersectionObserver/pull/192/files for spec changes. |
@szager-chromium I think your first change is what we should push for. But this might also require either an additional property (e.g. isIntersecting) in IntersectionObserverRegistration or another special value for previousThresholdIndex (e.g. -2) indicating a previous non-intersection. The latter is how we currently archive this behavior in Firefox. |
Yep, noticed this! 🙂 Just to make sure I understand correctly: it sounds like @szager-chromium you would like the spec to match Chrome's behavior (fire on Demo 1, don't fire on Demo 2), whereas @tobytailor you would like the spec to match Firefox's behavior (fire on both Demo 1 and Demo 2). Did I get that right? As for Edge, my team is still deciding how we want to tackle this. Edge's current implementation follows an older version of the spec, and we were a bit blindsided by recent changes (e.g. e2a5bfb, 9ce0b35). So I'm first trying to understand the motivating factor behind these changes. The case for |
@nolanlawson I would turn that question back on you: in the case of edge-adjacent intersections, what should the value of intersectionRatio be? As I understand it, the real question is whether, given a threshold of zero, we should send a notification when transitioning from is-intersecting-zero-intersection-ratio to is-intersecting-non-zero-intersection-ratio. That's the part that I consider debatable, and I can imagine arguments on both sides. There is an obvious workaround if you do, indeed, want that notification: construct your IntersectionObserver like this: new IntersectionObserver(myCallback, { threshold: [ Number.MIN_VALUE ] }) I don't really like that, though; it's hacky and non-obvious why you would need it. Part of the motivation behind adding the isIntersecting field was to avoid such shenanigans. |
As a naïve user, I would expect that However, looking back on the context for I'm asking these questions because I'm genuinely trying to understand the motivation behind the spec changes. As you say, there's a real question here about when exactly to fire events, and understanding the context helps. 🙂 |
In fact, intersectionRatio is 1 and not 0 for zero-area elements. See https://wicg.github.io/IntersectionObserver/#dom-intersectionobserverentry-intersectionratio. |
Thanks for the feedback! I've reviewed this issue with @scottlow and we've come to the following conclusions: 1. We agree with @szager-chromium on this:
2. As for where the spec says this:
This is a bug in the spec, because in e.g. the case where an element's starting 3. In the second demo, where three list elements are intersecting but the third is edge-adjacent, we feel Chrome's behavior would be surprising to web authors, because it fires no events for either the first element or the third one. So we'd prefer to match Firefox's implementation. However, it's not clear how to amend the spec to achieve this behavior. Most importantly, we want to avoid the situation where an element crossing a root boundary fires two events: one for edge-adjacency ( So @tobytailor if you could fill us in on Firefox's current implementation with the |
We start by initializing an elements previousThreshold value with -2. When testing for intersection. thresholdIndex starts out with -1 and in case of an intersection gets set to the actual threshold index, according to the algorithm described in the spec. That means when running the algorithm on an element for the very first time, the result will always be different to the previousThreshold (being -2), whether its intersecting or not. This guarantees an initial notification when starting to observe an element. From that point on, previousThreshold is always >= -1. |
@tobytailor Hm so it sounds like by adding an extra boolean to track whether we've run the algorithm yet or not, we could avoid the |
I've looked into this a bit more, and it appears that Firefox's implementation actually doesn't solve the issue of the double-fire. You can see it in this demo: This appears to be a drawback of the "fire when either isIntersecting or previousThreshold changes" approach. Assuming the user scrolls slowly enough (or you set scrollTop manually, as I do in the demo), you can get a double-fire when the element crosses its root boundary. Based on this, it seems @szager-chromium's original suggestion may be the best one. The Demo 2 case is indeed odd in Chrome given that you can effectively never get an event fired for any element no matter how much you scroll, but that'll only occur in the very unusual case where an element is both at the bottom of a list and perfectly lines up with its root on the top, so maybe it's not worth bending over backwards to accommodate. |
On Chrome: 53.0.2785.135, Android: 7.1.1, there is no isIntersecting in IntersectionObserverEntry, and the intersectionRatio is 0 when it is zero intersection. |
Chrome 53 is 7 versions old and is at 0.08% global usage according to caniuse.com… is there a strong reason to support it? |
@nolanlawson Sorry for reporting this problem late. |
This is a quick note that we are opting to match Chrome's behavior in our next release (EdgeHTML 16), due to the double-fire issue described above as well as general webcompat. You can preview it in the latest public insider build (16275). So a PR should probably be opened on the spec to adopt @szager-chromium's suggestion, unless there are objections. |
Attempts to satsify the spec: https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo isIntersecting, non-zero area, and display:nonen are all related, so fixing in one swoop. Fixes: #93 #73 Related issues: w3c/IntersectionObserver#69 w3c/IntersectionObserver#222
Attempts to satsify the spec: https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo isIntersecting, non-zero area, and display:nonen are all related, so fixing in one swoop. Fixes: #93 #73 Related issues: w3c/IntersectionObserver#69 w3c/IntersectionObserver#222
Attempts to satsify the spec: https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo isIntersecting, non-zero area, and display:nonen are all related, so fixing in one swoop. Fixes: #93 #73 Related issues: w3c/IntersectionObserver#69 w3c/IntersectionObserver#222
Attempts to satsify the spec: https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo isIntersecting, non-zero area, and display:nonen are all related, so fixing in one swoop. Fixes: #93 #73 Related issues: w3c/IntersectionObserver#69 w3c/IntersectionObserver#222
Attempts to satsify the spec: https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo isIntersecting, non-zero area, and display:nonen are all related, so fixing in one swoop. Fixes: #93 #73 Related issues: w3c/IntersectionObserver#69 w3c/IntersectionObserver#222
Attempts to satsify the spec: https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo isIntersecting, non-zero area, and display:nonen are all related, so fixing in one swoop. Fixes: #93 #73 Related issues: w3c/IntersectionObserver#69 w3c/IntersectionObserver#222
Attempts to satsify the spec: https://www.w3.org/TR/intersection-observer/#update-intersection-observations-algo isIntersecting, non-zero area, and display:nonen are all related, so fixing in one swoop. Fixes: #93 #73 Related issues: w3c/IntersectionObserver#69 w3c/IntersectionObserver#222
Believe it or not, it's 2024 and I am working on supporting Chrome 53 and 56 as they shipped with LG webOS and Samsung Tizen TVs that are unupgradable. Is there a workaround for Edit: This polyfill works a treat. |
(Forking discussion from #211)
There are incompatibilities between Chrome, Edge, Firefox, and the spec on when exactly observer events should fire.
According to the spec:
And
So IntersectionObserverEntrys (events) should only be fired when the
thresholdIndex
changes. However, what we've observed in our testing is that Chrome fires this event whenisIntersecting
changes, regardless of whetherthresholdIndex
changes (which we can observe throughintersectionRatio
).So for example, here is a test showing Chrome firing an extra event for an element whose
intersectionRatio
does not change but whoseisIntersecting
has changed. And here are the cross-browser results:And here is a test showing Chrome not firing an event for an element whose
isIntersecting
hasn't changed, but whoseintersectionRatio
has changed. And here are the cross-browser results:So roughly, here's the results with a ✔️ for event fired, and ❌ for event not being fired:
Currently we (EdgeHTML) are weighing the options in our own implementation, but I'm interested to hear what Blink/Gecko folks think about this.
The text was updated successfully, but these errors were encountered: