Scroll position not preserved on child order change
Reported by
joni.sa...@wunderdog.fi,
May 29 2017
|
|||||||
Issue descriptionUserAgent: 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:
,
Jun 1 2017
,
Jun 2 2017
,
Jun 2 2017
,
Jun 8 2017
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.
,
Jun 8 2017
skobes@ I am assigning it to you for investigation given your recent work around scroll anchoring.
,
Jun 8 2017
,
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.
,
Jul 15 2017
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/
,
Jul 15 2017
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.
,
Jul 29 2017
> 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.
,
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).
,
Jan 7
skobes@ are there any further actions for this bug?
,
Jan 10
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 |
|||||||
Comment 1 Deleted