0

When I scroll some list during heavy render (for example 50 Highchart items) I have scroll freeze (and that is fine). The problem is after all charts are loaded there is a "jump" of a scroll (that was frozen) to the end of the list (up or bottom, depends on scroll direction). Is there a way to continue scrolling from the scroll position, say 30%, after all of the heavy renderings is completed?

I have tried to add styling for a list element that removes scrolling like "overflow: hidden" before the start of heavy render, then add "overflow: scroll" back to the element after all rendering is over. But that doesn't help, still experience "jumps".

What I have tried looks like this:

// inner-container is a class name of all scrollable elements on the page that I need to control
// content-wrapper is a list inside of the container, position for that I want to be consistent after a render (without "jumps")

const elements = document.getElementsByClassName("inner-container");
window.elCoords = [];
for (let el of elements) {
   el.style.overflowY = 'hidden';
   el.style.pointerEvents = 'none';
   const coords = el.getElementsByClassName('content-wrapper')[0].getBoundingClientRect();
   window.elCoords.push(coords.y)
}

After render is over, I remove "overflow: hidden" styling so that elements are able to be scrollable again and set scroll position as it was before heavy render start:

const elements = document.getElementsByClassName("inner-container");
let index = 0;
for (let el of elements) {
   const inner = el.getElementsByClassName('content-wrapper')[0];
   inner.scrollTo({
      top: window.elCoords[index],
      behavior: 'smooth'
   });
   index += 1;

   el.style.overflowY = 'scroll';
   el.style.pointerEvents = 'all';
}

Actual: after the heavy render is over, scroll position jumps to the end/start of the scrollable container

Expected: after the heavy render is over, scroll should continue from the position it was before heavy render start

1 Answers1

1

The browser is single-threaded. While your calculations are running, UI events aren't actually blocked but they are queued (scroll events, mouse events, keyboard events, etc.). When execution can continue, the queue is flushed, so any scrolling that occurred as well as any other events are played forward.

Before your calculations begin, you could prevent scrolling on the page and allow it again once the calculations have finished:

function preventDefault(event) {
  event.preventDefault();
}

document.addEventListener('scroll', preventDefault);
// and other events ('wheel', DOMMouseScroll', etc.)
// Heavy rendering...
// ...
document.removeEventListener('scroll', preventDefault);

or:

window.onscroll = function () { window.scrollTo(0, 0); };
// Heavy rendering...
window.onscroll = null;
skyline3000
  • 6,896
  • 1
  • 20
  • 32
  • thanks for the idea. I will try that and let you know if that works. I will accept the answer if that solves a problem – Alexander Solovyev Aug 21 '19 at 14:46
  • it seems that preventDefault no longer works for scroll because of passive event nature. – Alexander Solovyev Aug 21 '19 at 15:59
  • There are actually many different scrolling methods you have to disable to truly prevent all scrolling. See this question and answer which covers them https://stackoverflow.com/questions/4770025/how-to-disable-scrolling-temporarily. I've updated my answer to provide a simpler case which should also do the trick. – skyline3000 Aug 21 '19 at 19:06