IntersectionObserver uses padding edge instead of content edge to calculate intersectionRect with overflow clip
Categories
(Core :: Layout, defect)
Tracking
()
Tracking | Status | |
---|---|---|
firefox120 | --- | fixed |
People
(Reporter: jelmer, Assigned: emilio)
References
(Blocks 1 open bug)
Details
Attachments
(1 file)
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Steps to reproduce:
- See demo: https://codepen.io/jelmerdemaat/pen/wvjLMRN
- Notice InterSectionObserver's root is the <section> element which has overflow-x: auto;
- Notice the intersection root has padding-left and padding-right of 4em, making the content area smaller than the border area.
- When scrolling sideways through the root element, notice the changing numbers inside the items reflecting their own intersectionRatio.
Actual results:
When scrolling, the intersectionRatio of each item remains at 1.000 until the item reaches the border of the root element. This is incorrect. According to the spec (see link below) the IntersectionObserver must use the element’s content area to calculate the intersectionRect, which in this case would be inside of the 4em padding on both sides.
This means right now the reported intersectionRatio is incorrect.
Spec: https://www.w3.org/TR/intersection-observer/#intersectionobserver-content-clip
Expected results:
When scrolling, the intersectionRatio of each item should immediately start changing as it is immediately starting to intersect with the content-area of the root element. This is correctly visible when using Chrome (v106).
Comment 1•2 years ago
|
||
The Bugbug bot thinks this bug should belong to the 'Core::Layout' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.
Comment 2•2 years ago
|
||
AFAICS this looks valid: the example should take the "has a content clip" option in https://w3c.github.io/IntersectionObserver/#intersectionobserver-root-intersection-rectangle and therefore use the content area, not the bounding box.
Emilio, you've touched IntersectionObserver in the past, maybe you can have a look?
Assignee | ||
Comment 3•2 years ago
|
||
An Element is defined as having a content clip if its computed style has overflow properties that cause its content to be clipped to the element’s padding edge.
But we're not clipping to the content box... So this behavior seems fairly unintuitive? I think the intent of the spec is to clip to the scrollport (i.e., exclude scrollbars), which is what we do and I think is strictly better. I'll file a spec issue.
Assignee | ||
Updated•2 years ago
|
Reporter | ||
Comment 4•2 years ago
|
||
Thanks for the response! I agree, that's rather confusing. Even more so because if "clipped" in this case means "visually hidden", then this can never be true:
An Element is defined as having a content clip if its computed style has overflow properties that cause its content to be clipped to the element’s padding edge.
Because as far as I know, there is no CSS overflow property that can ever clip (visually hide) any elements content to its padding edge. Content always stays visible inside the padding area when you use any overflow value. This also seems preferable to me (and consistent cross browser since a very long time).
Focussing on the initial issue, I would argue that it is much more convenient to have the IntersectionObserver intersectionRatio
act as described in "Expected results" above. It gives the author the option to specify a root "padding" in CSS that is dynamic, while only initiating the IntersectionObserver once.
For example, in my use case this root padding varies per media query (screen width). That means you only have to author the CSS using media queries to change the root padding of the IntersectionObserver. As it uses this padding edge to calculate the intersectionRatio
. If this were not possible (using only the border edge), you'd have to re-initiate an IntersectionObserver instance for every media query change, with a new 'rootMargin' option. That would definitely (1) be more work, (2) mean variable duplication in CSS and JS and (3) have performance drawbacks.
Are there any updates here? Running into similar issues as Jelmer, where things work correctly everywhere except for Firefox. I agree that the spec is a little confusing, but it seems to be far more useful to have things clip to the content-box - like Chrome and Safari. Have a pretty similar use case as mentioned above where dynamic padding is a much simpler option as opposed to re-initializing IntersectionObserver each time something changes. Thanks!
Assignee | ||
Comment 6•1 year ago
|
||
I'll push to get the spec issue fixed. But I think Firefox's behavior is correct. IntersectionObserver generally uses clips, so if we're not clipping to the content box it doesn't make sense to use that.
Assignee | ||
Comment 7•1 year ago
|
||
This is a spec issue. See the test. The element is completely visible,
so the intersection ratio should be 1.
Spec issue: https://github.com/w3c/IntersectionObserver/issues/504
Spec PR: https://github.com/w3c/IntersectionObserver/pull/517
Updated•1 year ago
|
Assignee | ||
Updated•1 year ago
|
Comment 10•1 year ago
|
||
bugherder |
Reporter | ||
Comment 12•1 year ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #7)
Created attachment 9359053 [details]
Bug 1796268 - Add a test for IntersectionObserver root with clip and padding. r=#layoutThis is a spec issue. See the test. The element is completely visible,
so the intersection ratio should be 1.Spec issue: https://github.com/w3c/IntersectionObserver/issues/504
Spec PR: https://github.com/w3c/IntersectionObserver/pull/517
Thanks for picking this one up Emilio.
My expectations as a developer differ. For the reasons listed in my earlier comment. What is the right way for me to address this? Should I file a new issue in the spec, regarding my use case / issue?
Assignee | ||
Comment 13•1 year ago
|
||
Yes, please do. It seems related to https://github.com/w3c/IntersectionObserver/pull/486 too, not sure if that'd be enough to address your use case. you kinda just want the rootMargin to be -1 * padding automatically, right?
Description
•