New issue
Advanced search Search tips

Issue 727239 link

Starred by 2 users

Issue metadata

Status: WontFix
Owner:
Closed: Jan 10
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 2
Type: Bug



Sign in to add a comment

Scroll position not preserved on child order change

Reported by joni.sa...@wunderdog.fi, May 29 2017

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.71 Safari/537.36

Steps to reproduce the problem:
1. Have enough child elements inside parent element for scrolling
2. Scroll to bottom or anywhere in between (not to the top) 
3. Move child within parentElement using insertBefore: parentElement.insertBefore(parentElement.children[0], null)
4. scrollY position is changed

Here is a JSFiddle to illustrate the problem https://jsfiddle.net/6hbhgxjt/5/

What is the expected behavior?
Scroll position should be preserved

What went wrong?
Scroll position was not preserved

Did this work before? N/A 

Does this work in other browsers? Yes

Chrome version: 59.0.3071.71  Channel: beta
OS Version: OS X 10.12.6
Flash Version:
 
chrome-buggg.m4v
250 KB Download

Comment 1 Deleted

Labels: -Needs-Triage-M61 Needs-Triage-M59
Components: Blink
Components: -Blink Blink>Scroll
Status: Untriaged (was: Unconfirmed)
Cc: tkent@chromium.org bokan@chromium.org skobes@chromium.org
Owner: skobes@chromium.org
Status: Assigned (was: Untriaged)
Summary: Scroll position not preserved on child order change using DOM El (was: Scroll position not preserved on child order change)
I can confirm this is happening on Chrome. Firefox and Safari both work correctly.

IIRC, we normally adjust scroll position if there has been a change in the scrollable content or its scroll viewport. So it seems like we are needlessly notifying the scrollable area in the middle of append operation e.g., perhaps by causing a layout.

+tkent@ can you (or someone in DOM team) advise if the above situation is possible with Node.appendNode, prepend, replaceNode, insertBefore etc. 


skobes@ I am assigning it to you for investigation given your recent work around scroll anchoring. 
Summary: Scroll position not preserved on child order change (was: Scroll position not preserved on child order change using DOM El)

Comment 8 by tkent@chromium.org, Jun 8 2017

> advise if the above situation is possible with Node.appendNode, prepend, replaceNode, insertBefore etc. 

Though I don't have a concrete idea, it's possible that DOM mutation code unexpectedly triggers force layout in the middle of a mutation.


I have a similar problem, a library that i am developing is trying to accomplish a virtual scrolling tree view. But the scroll position(aka scrollTop) keep changing unexpectedly, when there are some of children nodes removed and added. See the question link https://stackoverflow.com/questions/44995749/weird-scroll-behavior-in-latest-blink-included-browsers-like-chrome-opera and the demo link https://embed.plnkr.co/GpQBZsguhZZOQWWbZnqI/
a keypoint is only blink-series browsers have this problem. Firefox, and edge work fine. Even some old version browsers work fine, but i don't know their version, coz they are some shelled browsers from Chinese company, like UC browsers, 360 se.
> Though I don't have a concrete idea, it's possible that DOM mutation code unexpectedly triggers force layout in the middle of a mutation.

I find out if i call `getBoundingRect` will trigger force layout.

Comment 12 by bokan@chromium.org, Jul 31 2017

Re 9/10/11: Assuming scroll anchoring is getting in your way here. In your case, since you're manually managing the scroll offset I think you'll probably want to disable anchoring with the `overflow-anchor` property (see: https://wicg.github.io/ScrollAnchoring/#exclusion-api). 
skobes@ are there any further actions for this bug?
Status: WontFix (was: Assigned)
Comment #12 is correct, this behavior is caused by scroll anchoring.  The flow is:

1. "Elem 1" div is reordered to come after "Elem 2" in the DOM, triggering layout.
2. Before the layout, ScrollAnchor walks the DOM and finds "Elem 2" to anchor to.
3. The layout moves "Elem 2" to the top.
4. ScrollAnchor adjusts the scroll position to follow "Elem 2".

The slightly weird thing here is that we compute the anchor node after the DOM change and not before.  This is the "performance optimization" mentioned in section 2.1 of the scroll anchoring spec, which wasn't supposed to have observable side effects.  If we computed the anchor node before the DOM change, we would anchor to "Elem 1" instead.

Unfortunately it's too expensive to recompute the anchor node after every scroll event, or before every DOM change.  And even if we could it would be of questionable benefit as scrollers that reorder their DOM elements would still see scroll anchoring adjustments (in this case "Elem 1" moves the same distance, but in the opposite direction) and likely want to set overflow-anchor: none.

Sign in to add a comment