wilsonpage / fastdom

Eliminates layout thrashing by batching DOM measurement and mutation tasks
6.83k stars 240 forks source link

Best time to update scroll position to minimize visual changes #128

Open CodeWithOz opened 2 years ago

CodeWithOz commented 2 years ago

I have a scenario where I want to render a list at a certain scroll position that's not 0. If I update scroll after rendering the list, I can see a brief period where the list is at scrollTop = 0, before it changes to the new scrollTop value. This corresponds to code like this:

const listHtml = '<ul>...</ul>'
requestAnimationFrame(() => {
  listContainer.innerHTML = listHtml;
  setTimeout(() => listContainer.scrollTop = nonZeroValue, 0);
});

This brief period looks like a flash of content because it's so quick. To prevent it, I set the scroll position directly inside rAF immediately after rendering the list items. So that code above became this:

const listHtml = '<ul>...</ul>'
requestAnimationFrame(() => {
  listContainer.innerHTML = listHtml;
  listContainer.scrollTop = nonZeroValue;
});

This took away the flash, the scroll position is set immediately the items are rendered. However, this significantly slows down the time it takes to actually paint the rendered list items.

So my question is what's the right time to update scroll position to both avoid the flash and minimize the delays to layout/painting?

wilsonpage commented 2 years ago

Good question! I don't have direct experience with this but I'm sure there's a perfect moment. You could always hide the lost with opacity: 0 until you've set the scrollTop, then fade it in. Not ideal though.

Please let me know what solution you find works best.

On Tue, 8 Feb 2022, 13:06 Uche Ozoemena, @.***> wrote:

I have a scenario where I want to render a list at a certain scroll position that's not 0. If I update scroll after rendering the list, I can see a brief period where the list is at scrollTop = 0, before it changes to the new scrollTop value. This corresponds to code like this:

const listHtml = '

    ...
'requestAnimationFrame(() => { listContainer.innerHTML = listHtml; setTimeout(() => listContainer.scrollTop = nonZeroValue, 0);});

This brief period looks like a flash of content because it's so quick. To prevent it, I set the scroll position directly inside rAF immediately after rendering the list items. So that code above became this:

const listHtml = '

    ...
'requestAnimationFrame(() => { listContainer.innerHTML = listHtml; listContainer.scrollTop = nonZeroValue;});

This took away the flash, the scroll position is set immediately the items are rendered. However, this significantly slows down the time it takes to actually paint the rendered list items.

So my question is what's the right time to update scroll position to both avoid the flash and minimize the delays to layout/painting?

— Reply to this email directly, view it on GitHub https://github.com/wilsonpage/fastdom/issues/128, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHZFB3XUON4YPXEH4ANAOTU2FSS3ANCNFSM5N3LD5BQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you are subscribed to this thread.Message ID: @.***>

CodeWithOz commented 2 years ago

Thanks for the suggestion! Yeah using opacity like that won't be ideal.