react-scroll-to-bottom icon indicating copy to clipboard operation
react-scroll-to-bottom copied to clipboard

Loosing stickiness on simultaneous inserts&removals

Open Rulexec opened this issue 5 years ago • 7 comments

Hello.

I have a list of messages with frequent additions. Messages have random height (they are text with word wrap). This list also have a limit of messages, when there is more messages than a limit — old messages should be hidden.

In such circumstances after some time scrolling to bottom stops.

I prepared demo, that illustrates this behavior — https://github.com/Rulexec/react-scroll-to-bottom/tree/limited-scroll-demo

2020-07-30Z17-49-14

Rulexec avatar Jul 30 '20 14:07 Rulexec

Wow, thanks for the repro in repo. Please keep it there. Will definitely look at it.

compulim avatar Aug 06 '20 20:08 compulim

I'm having the same issue. I think the problem is related to having a limit of messages. If I keep all the messages in the stream, scrolling works fine, even if sometimes there are multiple additions in very quick sequence. But if at the same time that I add new lines I remove old ones, scrolling breaks.

albireox avatar Jan 11 '21 04:01 albireox

I am seeing this one by removing the first paragraph, and adding a new one at the end.

Will fix it in next schedule.

compulim avatar Feb 01 '21 12:02 compulim

I am having the same issue, any news on when it will be resolved?

CharlieGroves avatar Apr 08 '21 10:04 CharlieGroves

I just added an automated test harness that will help reproducing this bug. I saw it too.

After I completed hygiene works on this repository (bump deps, add static code analysis, etc), I will work on this. This is a high priority bug.

compulim avatar May 16 '21 04:05 compulim

Done some investigations:

  • It only repro if elements inserted and removed are of same size
    • This also includes moving the first element to the end of the list (insert/remove of same size)

Root cause:

  • Interference with Chromium "artificial scroll" feature
  • Artificial scrolling, means:
    • At middle/bottom of the list, when an element at top is removed, Chromium will artificially scroll to keep the viewport unmoved
      • It means, scrollTop will change, and scroll event will be fired. scrollTop will be set to a number to keep the viewport unmoved, i.e. scrollTop -= elementRemoved.clientHeight
    • This reduce jumpy UX, end-user won't notice an element was removed because the viewport won't move, only the scrollbar handle will change its position
  • We have logic to differentiate whether the scroll event is done by the end-user or by Chromium
    • If it is by Chromium, we will keep it sticky
    • If it is done by end-user, we will unstick
      • E.g. mouse wheel, two-finger on precision touchpad, Xbox right joystick, two-finger on Synaptics driver (non-precision)
  • The insertion/removal caused a false positive in this check: we think the scroll is done by end-user, instead, it was done by Chromium
    • The check is: on scroll event, if the content height and scrollable height is kept unchanged, it is done by Chromium
  • Due to false positive, we unstick the view

To fix this issue, we will need to rewrite the logic.

compulim avatar May 17 '21 06:05 compulim

@compulim I fought with a similar problem in my library. As I remember it is related to scroll anchoring.

Try to add:

overflow-anchor: none

To your main scrolling div. I have tested it a bit with the @Rulexec repro and it seems to work.

Resources:

  • https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor/Guide_to_scroll_anchoring
  • https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor

supersnager avatar May 17 '21 07:05 supersnager