Would you use any libraries or build your own virtual scroll logic
Default to a battle-tested library (react-window, @tanstack/react-virtual, virtua) — they handle the gnarly edge cases. Build your own only when you have unusual requirements the libraries can't meet, and understand the core algorithm either way.
The honest senior answer: use a library by default, and know why. Building your own is a deliberate exception, not a flex.
Use a library — almost always
react-window, @tanstack/react-virtual, virtua, react-virtuoso. They've already solved:
- Scroll position math and the spacer/translate technique.
- Variable and dynamic row heights with measurement caches.
- Overscan buffering to avoid blank flashes.
- Scroll-to-index, sticky items, grids, horizontal scrolling.
- Resize handling, RTL, momentum scrolling quirks on iOS.
- Accessibility hooks.
These are the exact things that take weeks to get right and break in subtle ways. Reinventing them is rarely a good use of time.
Understand the core algorithm anyway
Interviewers want to know you could build it:
- A scroll container with a tall inner spacer sized to
totalCount × rowHeight(so the scrollbar is correct). - On scroll, compute the visible index range from
scrollTop,viewportHeight,rowHeight. - Render only
[startIndex - overscan, endIndex + overscan], absolutely positioned (ortransform: translateY) at their real offsets. - Variable heights → maintain a measured-height cache and a prefix-sum/position index to map scroll offset → index.
Build your own when…
- You have highly unusual layout (masonry, nested virtualization, a custom scroll model) the libraries don't support.
- You need to shave the dependency in a perf- or bundle-critical context.
- The library's abstraction fights your data model badly.
Even then, consider forking or wrapping a library before going from scratch.
How to frame it in an interview
"I'd reach for @tanstack/react-virtual — it's headless, handles dynamic heights, and is well-tested. I'd build my own only if we had a layout it couldn't express. Either way the algorithm is: spacer for scroll height, compute the visible window from scrollTop, render window + overscan, absolutely positioned." That shows judgment and depth.
Follow-up questions
- •Walk me through the core virtualization algorithm.
- •What makes dynamic row heights hard?
- •What accessibility issues does virtualization introduce?
- •When is the dependency cost of a virtualization library not worth it?
Common mistakes
- •Building from scratch to show off, then missing dynamic heights / iOS scroll quirks.
- •Using a library but not understanding the algorithm when asked.
- •Virtualizing short lists that don't need it.
- •Ignoring accessibility (find-in-page, screen readers) regressions.
Performance considerations
- •Virtualization caps DOM nodes regardless of dataset size, drastically cutting memory and layout cost. The tradeoffs: scroll-jank risk if measurement is expensive, and accessibility/SEO regressions. Libraries amortize the hard parts; rolling your own means owning all of it.
Edge cases
- •Dynamic, unknown-until-rendered row heights.
- •Scroll-to-index into unrendered rows.
- •Nested or 2D (grid) virtualization.
- •Variable content causing measurement thrash.
Real-world examples
- •@tanstack/react-virtual powering a 100k-row data grid.
- •react-window in a chat app's message list.