Closed Bug 1553673 Opened 6 years ago Closed 5 years ago

IntersectionObserver internal rounding error with certain negative percentage rootMargins

Categories

(Core :: Layout, defect, P2)

67 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla69
Tracking Status
firefox69 --- fixed

People

(Reporter: github, Assigned: emilio)

Details

Attachments

(1 file, 1 obsolete file)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0

Steps to reproduce:

  • Create an IntersectionObserver with a rootMargin that has a negative percentage of -30% or -70% for top and/or bottom margins
  • Observe an element with a height

Example here: https://codesandbox.io/embed/still-rain-u4gk0

Actual results:

  • The observed element will never trigger the observer

This bug also happens with the IntersectionObserver polyfill due to a rounding error in the implementation — it's possible that Firefox is suffering from the same bug at certain negative root margins

Expected results:

  • Do the same experiment in Safari or Chrome, and the element triggers the observer as expected
Component: Untriaged → Layout
Product: Firefox → Core

This works for me on Nightly, could you check on the latest Nightly?

Also, could you point to the polyfill issue so that I can see which kind of rounding error you're talking about?

Flags: needinfo?(github)

Hello Emilio!

I've updated the example to perhaps better reflect what I'm seeing — the pink boxes should turn yellow as you scroll. It works in Chrome and Safari, but doesn't work in Firefox Release or Nightly for me.

You can preview the page directly here (which seems to be a little more consistent) - the code itself is here.

I'm referring to the polyfill produced by W3C — where the polyfill reconciles a percentage-based rootMargin was where I found the rounding error when I last was debugging it (in Safari pre-IO support being added). After the it does the math it'd result in a margin that'd never be possible to hit due to rounding just past the threshold. I honestly have no clue if that's the same thing that's happening in Firefox, but it seemingly triggers in the same exact way. Even bumping offset by .1 percent is enough to make it work. (You can see this by changing offset to .301 - then Firefox will correctly intersect the elements.)

Flags: needinfo?(github)

I've updated the example to perhaps better reflect what I'm seeing — the pink boxes should turn yellow as you scroll. It works in Chrome and Safari, but doesn't work in Firefox Release or Nightly for me.

Right, I get that, it just worked fine for me :). It does work fine for me with the maximized window, fwiw.

You can preview the page directly here (which seems to be a little more consistent) - the code itself is here.

Thanks! Yeah, after playing a bit more with that URL, I could reproduce it with a viewport size of 960x691px.

I can try to take a look at what's going on when I have some time, but if somebody wants to steal it from me then please be my guest :-)

Here's where the margin calculation happens, fwiw.

Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(emilio)

It is indeed a rounding error:

(rr) p rootRect
$1 = {<mozilla::gfx::BaseRect<int, nsRect, nsPoint, nsSize, nsMargin>> = {x = 0, y = 0, width = 76080, height = 52380}, <No data fields>}
(rr) next
(rr) p rootMargin
$2 = {<mozilla::gfx::BaseMargin<int, nsMargin>> = {top = -36666, right = 0, bottom = -15715, left = 0}, <No data fields>}
(rr) next
(rr) p rootBounds
$3 = {<mozilla::gfx::BaseRect<int, nsRect, nsPoint, nsSize, nsMargin>> = {x = 0, y = 36666, width = 76080, height = -1}, <No data fields>}

The negative height (- 1 / 60th of a CSS pixel) makes it so that it never intersects with anything.

The default rounder floors percentages instead of rounding, which can cause
subtle issues.

This is generally desirable for most lengths, AIUI, so that pages don't cause
undesired overflow when using percentage widths and such, but for the
intersection observer root margin, it can cause some annoyance as the percentage
going negative may cause the root rect to be negatively sized and report no
intersection.

This also seems to match Blink1, though it goes back to the initial
implementation of IntersectionObserver.rootMargin2.

I'll send a patch, though I'm unsure of whether it's the best-available solution. Seems to be what other engines do though.

Assignee: nobody → emilio
Flags: needinfo?(emilio)

The priority flag is not set for this bug.
:jwatt, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jwatt)
Flags: needinfo?(jwatt)
Priority: -- → P2

The default rounder floors percentages instead of rounding, which can cause
subtle issues.

This is generally desirable for most lengths, AIUI, so that pages don't cause
undesired overflow when using percentage widths and such, but for the
intersection observer root margin, it can cause some annoyance as the percentage
going negative may cause the root rect to be negatively sized and report no
intersection.

This also seems to match Blink1, though it goes back to the initial
implementation of IntersectionObserver.rootMargin2.

Attachment #9071377 - Attachment is obsolete: true
Attachment #9068118 - Attachment description: Bug 1553673 - Round intersection observer percentage margins with NSToCoordRound rather than the default rounder. → Bug 1553673 - Round intersection observer percentage margins with NSToCoordRound rather than the default rounder. r=dholbert
Pushed by ealvarez@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/b743690bf1a5 Round intersection observer percentage margins with NSToCoordRound rather than the default rounder. r=dholbert
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/17274 for changes under testing/web-platform/tests
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla69
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: