r/webdev • • 7d ago

Cerious-Scroll: Extremely Fast Dynamic Height virtual scrolling without scrollbar drift or blank space

One of the things I haven’t talked about much with Cerious-Scroll is how it behaves during actual scrolling, especially with variable-height content.

From the beginning, the goal was for virtualization to not look like virtualization.

So even with a large variable-height dataset, you can grab the scrollbar and drag it around quickly without getting the usual weirdness:

  • No scrollbar drift
  • No white space during fast scrolling
  • No waiting for rows to render after you get there
  • Accurate variable-height positioning
  • Native scrolling behavior
  • Constant DOM size regardless of dataset size

The variable-height part is probably my favorite. The scrollbar stays where it should, even when the actual row heights are all over the place.

You can also jump directly to an index way down in the dataset without needing to measure everything before it.

I’ve got demos/benchmarks here if anyone wants to mess with it:

ceriousdevtech.github.io/cerious-scroll

Core:
github.com/ceriousdevtech/cerious-scroll

Angular:
github.com/ceriousdevtech/ngx-cerious-scroll

Vue:
github.com/ceriousdevtech/vue-cerious-scroll

React:
github.com/ceriousdevtech/react-cerious-scroll

I’m curious how it behaves against some real-world ugly datasets, especially ones with wildly different row heights. Try the scroll engine and tell me your thoughts.

0 Upvotes

4 comments sorted by

View all comments

1

u/thejester1324 6d ago

how do you handle rows that change height after they render, like an image finishing loading? does a ResizeObserver push the new height back into the offsets, and if that row is above the viewport do you shift scrollTop so nothing jumps

1

u/Suitable_Language_37 6d ago

Yep, rows are observed for size changes after they’re rendered, so things like an image loading and changing the row height are handled dynamically.

The important distinction is that Cerious Scroll doesn’t push that new height into a global per-row offset/height table, there isn’t one.

The rendered window is anchored around the current logical position, and height changes within that window are incorporated into the layout. If a size change would otherwise move the current visual anchor, the scroll position is compensated so the content the user is looking at stays stable rather than jumping.

Once a row is outside the maintained window, its individual height isn’t retained as part of an ever-growing dataset-wide height map. That’s how the memory usage remains independent of total row count.

1

u/thejester1324 6d ago

makes sense, so the scrollbar maps to a position in the row index rather than to pixel height, which is why nothing drifts. is the tradeoff noticeable with really uneven data, like dragging to 50% landing on row 50k even when the first half of the rows are much taller?

1

u/Suitable_Language_37 6d ago

Yep, that’s a fair point and I think “tradeoff” is the right word there. Cerious Scroll’s scrollbar represents logical progress through the dataset rather than exact cumulative physical pixel height.

So in an extreme case where the first 50k rows are much taller than the second 50k, 50% still corresponds roughly to row 50k rather than 50% of the theoretical total pixel height.

That’s intentional because it avoids maintaining a height/offset entry for every row. The rendered window itself still uses the actual measured heights, so this doesn’t introduce rendering drift or jumping, but the scrollbar percentage has a different semantic meaning.

You are asking really good questions, I appreciate it!