Closed Bug 1796268 Opened 2 years ago Closed 8 months ago

IntersectionObserver uses padding edge instead of content edge to calculate intersectionRect with overflow clip

Categories

(Core :: Layout, defect)

Firefox 106
defect

Tracking

()

RESOLVED FIXED
120 Branch
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:

  1. See demo: https://codepen.io/jelmerdemaat/pen/wvjLMRN
  2. Notice InterSectionObserver's root is the <section> element which has overflow-x: auto;
  3. Notice the intersection root has padding-left and padding-right of 4em, making the content area smaller than the border area.
  4. 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).

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.

Component: Untriaged → Layout
Product: Firefox → Core

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?

Severity: -- → S3
Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(emilio)
Summary: IntersectionObserver wrongly uses border edge in stead of content edge to calculate intersectionRect → IntersectionObserver wrongly uses border edge instead of content edge to calculate intersectionRect

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.

Flags: needinfo?(emilio)

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!

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.

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

Assignee: nobody → emilio
Status: NEW → ASSIGNED
Summary: IntersectionObserver wrongly uses border edge instead of content edge to calculate intersectionRect → IntersectionObserver uses padding edge instead of content edge to calculate intersectionRect with overflow clip
Pushed by ealvarez@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/75132d2a2bac
Add a test for IntersectionObserver root with clip and padding. r=smaug
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/42599 for changes under testing/web-platform/tests
Status: ASSIGNED → RESOLVED
Closed: 8 months ago
Resolution: --- → FIXED
Target Milestone: --- → 120 Branch
Upstream PR merged by moz-wptsync-bot

(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=#layout

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

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?

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?

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: