Closed Bug 1592094 Opened 3 years ago Closed 3 years ago

[scroll anchoring] Elements jump up and down after scrolling

Categories

(Core :: Layout: Scrolling and Overflow, defect, P3)

70 Branch
defect

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: dandromb, Unassigned)

References

(Blocks 1 open bug)

Details

Attachments

(1 file, 6 obsolete files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0

Steps to reproduce:

  • Visit an affected site, where an element has dynamic height (usually an expanding/shrinking header), or with infinite scroll (the page gets longer when loading new content)
  • Scroll down/up a bit while using the page

Actual results:

After a while one of the following may happen:

  • Dynamically-sized element (e.g. the header) gets stuck in a loop, shrinking/expanding
    OR
  • Elements on the page endlessly jump up and down (with no obvious dynamically sized element animating)

Expected results:

Elements should simply move (up or down) once, ending up in the spot where they're supposed to end up, without an infinite loop of jumping up/down.

I have seen the infinite jump up/jump down loop intermittently on the following pages:

Affected versions: Has happened for the past several releases.

OS/Platform: Definitely seen it on Windows, but also on Linux I think.

Hardware: I tend to use older machines with integrated GPU or so old that hardware acceleration is disabled. Not sure if external GPU/hardware acceleration would affect this or not.

Component: Untriaged → Layout
Product: Firefox → Core
Status: UNCONFIRMED → NEW
Ever confirmed: true
Summary: Elements jump up and down after scrolling → [scroll anchoring] Elements jump up and down after scrolling

I cannot reproduce the issue on Reddit and representedwomen.org on Nightly, do you know if it repros there?

I can reproduce the issue in bisnow.com though.

Flags: needinfo?(dandromb)
Component: Layout → Layout: Scrolling and Overflow

And if you can reproduce them, can you check that setting layout.css.scroll-anchoring.enabled=false in about:config fixes them?

Attachment #9104925 - Attachment is obsolete: true

Similar to your results, I can reproduce on Nightly at bisnow.com, but having trouble reproducing the other two sites.
And yes, setting layout.css.scroll-anchoring.enabled=false seems to fix it for that site.

Flags: needinfo?(dandromb)
Attached file More reduced test-case. (obsolete) —
Attachment #9104926 - Attachment is obsolete: true

Not sure if it's related, but feels like it might be: When I scroll and then click a link, Firefox sometimes loads a nearby link instead. Often on Reddit, my mouse will be over one "card" for one post, then I scroll, and click the "card" below... The prior "card" (which is now above my cursor and almost off-screen) is the one whose link ends up actually loading.

I posted that a while ago as bug 1446852.

(But toggling layout.css.scroll-anchoring.enabled has no impact on that -- no impact on what I described in bug 1446852 -- so maybe it is not related after all.)

(Sorry for some short, disorganized comments...)

A correction to my comment 0/comment 1: The Reddit issue is not elements jumping up and down.

The Reddit issue is as follows:

  • Trigger infinite scroll to load more posts ("cards")
    • First, the page lengthens to give space for added cards, but shows an empty gray background until the new cards finish loading.
    • Some of the new cards will load in, and the bottom-most new card will display only half-way down, like a CRT TV scanning half-way through a frame.
    • What is weird is, the lowest, furthest-rendered portion of the card will flicker up/down by about 20 pixels.
      • Bottom 20 pixels alternates between showing a bit of the new card, back to just empty grey, and back to showing 20px more of the card, in a loop.
    • Once the cards actually finish loading, which takes about 5-10 seconds, the flicker goes away.

Slight correction again about Reddit: The bottom portion of the site flickers, content cards and cards from the sidebar, everything flickers away revealing blank background for several vertical pixels worth of the page, at the bottom extent of the rendered page. (Page is longer than the amount of the page with rendered/non-flickering contents.)

Could you record a scrrencast of that? Also does the scroll-anchoring pref fix it for reddit as well? Otherwise it's an unrelated issue.

Attached file Fully reduced. (obsolete) —
Attachment #9104951 - Attachment is obsolete: true
Attached file Further reduced. (obsolete) —
Attachment #9104990 - Attachment is obsolete: true
Attached file Even simpler test-case (obsolete) —

(overflow-anchor is not needed to reproduce, but proves that the difference is not in anchor selection, that is, it just forces #content to be selected as the anchor).

So, I think this is all working per spec. The anchor should be <div id="#content"> (I've just made the otehr nodes overflow-anchor: none to ensure that the anchor isn't selected elsewhere, even though it shouldn't).

The website is moving the anchor up by shrinking the height of #fakeHeader, and thus the engine is expected to correct that offset by scrolling back to the top and firing an scroll event (which would in turn expand the header and do the opposite, causing the flickering observed here).

https://drafts.csswg.org/css-scroll-anchoring/#suppression-triggers doesn't mention overflow at all, and mentions suppressing adjustments only if the computed height property changes in the scroll anchor or one of its ancestors. The page keeps a fixed header and an in-flow #fakeHeader of the same height, so there's no position change or other such property. So tldr none of those clauses apply and we should apply the adjustments.

Now, there are multiple things that make the test-case not reproduce the issue:

Not changing overflow

If you don't change overflow (which in Gecko reframes and thus causes a harder relayout than just changing height) you would hit our version of this chromium bug.

That is, we queue scroll anchor adjustment requests when the scroll frame is reflowed, or when a node in the anchor chain is reflowed and is the root of the reflow.

So without the overflow change we'll miss it and not request an adjustment at all (which to be clear is wrong). My guess is that this is why the website works in Chromium.

Various timing differences

If you use something else than setTimeout(.., 0), the bug goes away immediately.

  • If you don't delay the thing, then the heuristic described here comes into play and works, great!

  • If you delay it enough such as that you've processed another scroll event, then the bug doesn't reproduce, because on that second scroll event you schedule an update that overrides the first, and afterwards the next scroll event is also consistent so you get into a stable state without flickering.

So the only meaningful behavior differences between browsers are:

  • The layout optimizations that they perform which cause bugs that in this case make the page work.

  • The scheduling between scroll events and timers (which can differ for various legit reasons).

And thus, I have no idea how to go about fixing this, so far, other than tracking the timeout as "coming from the scroll event", maybe, and treating it the same.

In terms of the page's author, they could just remove the setTimeout, I'd think, or set overflow-anchor: none on the document element.

Attachment #9105001 - Attachment is obsolete: true

The attachment above had the timeout removed for debugging whoops.

Attachment #9105055 - Attachment is obsolete: true

Will update you if I can reproduce this odd behavior on the other two pages. Happens much more often/more consistently on bisnow.com.

(In reply to Dan D (volunteer tester from the community) from comment #17)

Will update you if I can reproduce this odd behavior on the other two pages. Happens much more often/more consistently on bisnow.com.

Bug 1592474 should've made this much better by stopping after detecting the flickering, can you confirm that? Thanks!

Dan D ^

Flags: needinfo?(dandromb)
Priority: -- → P3

Hi again. I am trying on Nightly and Release (70.0.1) on just my Linux machine (with as far as I can tell no graphics card to speak of, even integrated. Or if there is one, it's really basic and old -- it doesn't qualify for WebRender, for example). This is the only PC I have access to test on right now and the foreseeable future.

I can't reproduce on any sites, nor the reduced testcase. Neither in Nightly nor Release (70.0.1). Either the fix has been backported somehow to Release channel, or else my particular machine is no longer affected.

I'm not sure why this is the case, but that's all the update I can give at the moment.

Flags: needinfo?(dandromb)

Thanks for being involved. I am going to mark this as WORKSFORME, and drop bug 1592474 in the dependency list (instead adding it in See Also).

Please feel free to reopen this if you see the same symptoms.

Status: NEW → RESOLVED
Closed: 3 years ago
No longer depends on: 1592474
Resolution: --- → WORKSFORME
See Also: → 1592474
You need to log in before you can comment on or make changes to this bug.