question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[STICKY] Should I drop scaling support?

See original GitHub issue

Browsers have maximum limits on clientHeight & clientWidth (and by extension on maximum scroll offset). Positioning content beyond this limit will result in it not being visible (even though it is in the DOM). Starting with version 7.3.0, react-virtualized introduced a feature that auto-scales clientHeight & clientWidth to keep them within safe limits. Beyond a certain threshold, react-virtualized scales down width, height, and scroll position so that the browser can display more information than it would normally be able to.

Unfortunately these limits vary widely by browser (eg Chrome is safe up to 33.5M pixels, or in many cases beyond, but Edge maxes out at 1.5M pixels). Until this point I have tried to support the lowest common denominator, lowering my scaling threshold to accommodate Edge limitations. This has a major drawback though: it causes scaling to feel too fast when the scaling factor gets too large. This results in a sub-par scrolling experience for browsers that could easily handle the clientHeight (eg Firefox, Chrome) in order to not break Edge.

I have considered attempting a browser-specific threshold as it would improve the UX for Chrome and Firefox. I have not implemented one yet though because I have not found any authoritative/official documentation on which browsers have which limits (eg on Chrome it seems to vary by operating system).

I’m opening this issue for discussion of the following:

Do you know more about this topic than me?

(I know very little.) Perhaps you could refer me to any official browser vendor documentation about this. Alternately any OSS project that already detects/encodes these limits.

If I found an official list I could at least increase the threshold for Chrome and Firefox and improve the UX in those browsers.

Do you think I should continue to implement scaling in react-virtualized?

Or should I leave it up to whatever the browser’s native limitations are? An alternative to this could be that I disable scaling by default but give users a way to opt-in.

One argument for dropping scaling is that past a certain point it results in a horrible user experience anyway. (If scrolling a few pixels will jump you forward tens or hundreds of rows, the list view is mostly useless anyway.)

It may also result in slight performance improvements as I would be doing less in each scroll event handler.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:15 (8 by maintainers)

github_iconTop GitHub Comments

3reactions
sophiebitscommented, Sep 19, 2016

I tried to articulate a solution in my tweet https://twitter.com/soprano/status/777649671783284737 but I’m not sure I did it clearly so here’s a longer version.

It’s my understanding that the current react-virtualized code is akin to

const maxDimension = 1500000;
const scaleFactor = listLogicalHeight / maxDimension;

function onScroll() {
  const physicalTop = list.scrollTop;
  const logicalTop = scaleFactor * physicalTop;

  rerenderRows(physicalTop, logicalTop);
}

Here I’m assuming a rerenderRows function that renders the rows whose logical positions are near logicalTop and sets their positions to be near physicalTop so that the rows appear in the list viewport.

My proposed (much more complicated) alternative wouldn’t adjust small changes in scroll position at all, but large jumps would be treated essentially the same as the current scaling so that it is easy to jump to 30% of the way through a list, for example.

const maxDimension = 1500000;
const scaleFactor = listLogicalHeight / maxDimension;

const currentPhysicalTop = 0;
const currentLogicalTop = 0;

function onScroll() {
  const physicalTop = list.scrollTop;
  const physicalDiff = physicalTop - currentPhysicalTop;

  if (Math.abs(physicalDiff) < 2 * listViewportHeight) {
    // Small scroll -- preserve delta in scroll position
    currentPhysicalTop += physicalDiff;
    currentLogicalTop += physicalDiff;

    // If you were to scroll forever with small scrolls, eventually you would
    // hit the end of the physical list before reaching the end of the logical
    // list. So we fix the physical scroll position when we get a chance.
    fixPhysicalScrollPosition(Math.round(currentLogicalTop / scaleFactor));
  } else {
    // Big scroll -- don't try to preserve delta in scroll position
    currentPhysicalTop = physicalTop;
    currentLogicalTop = scaleFactor * physicalTop;
  }

  rerenderRows(currentPhysicalTop, currentLogicalTop);
}

const fixPhysicalScrollPosition = debounce(function(correctPhysicalTop) {
  list.scrollTop = correctPhysicalTop;

  currentPhysicalTop = correctPhysicalTop;
  rerenderRows(currentPhysicalTop, currentLogicalTop);
}, 1000);

This is pseudocode and is also logically incomplete: at the very least, it is one-dimensional. It also does not attempt to guarantee that scrolling to the top of the list would be correctly interpreted as scrolling to the top of the list. I imagine you’d want to dedicate a few screenfuls at the top and bottom of the list to have 1:1 scrolling and only apply scaling in the middle parts.

2reactions
bvaughncommented, Dec 4, 2016

Note to self: The changes discussed above could also help improve the RTL and reverse list use cases. If we choose the initial indices to render at a given scroll offset based on the % within the total scrollable area, we could avoid having to pre-measure and cache positions before that offset. This would improve performance for cases that are currently awkward due to cached position invalidation.

I still plan (hope) to make time to work more on this idea soon.

Read more comments on GitHub >

github_iconTop Results From Across the Web

CSS Position Sticky weird behvaiour when scale applied to ...
I tracked the issue down to the scaling not being applied to the rptDisplay but being applied to a child of display but...
Read more >
Autoscaling guidance - Best practices for cloud applications
Review autoscaling guidance. Autoscaling is the process of dynamically allocating resources to match performance requirements.
Read more >
Scale Management Guidelines--UC IPM
Regularly monitoring honeydew beneath plants, such as the number of drops during four hours on the same time of day once a week,...
Read more >
Sticky Leaves On Houseplants - What Causes It, Help And ...
Sticky Leaves Treatment – Controlling Scale​​ Scale “breathes” through their “armor.” The easiest way to kill the scale is by suffocation. There are...
Read more >
How To Get Rid Of Scale Insects On Houseplants, For Good!
Sometimes this is one way to help with plant scale identification if you're unsure. As they feed, scale insects excrete a sticky residue...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found