Virtualization Technique
MediumThe problem
Every rendered row is real DOM to build, style, lay out, paint, and keep in memory. At 10,000 rows that cost stops being free:
- the first render blocks while the browser lays out every node;
- memory tracks the total node count, not what is visible;
- scrolling drops frames because each one touches a huge tree.
Only about 8 rows are ever on screen. The other 9,992 are built and painted for nothing.
Step through it
Scroll the 10,000-row inbox and watch the DOM node count stay tiny. Step through the concepts, toggle naive versus virtualized, and adjust the overscan to see the math in action.
How windowing works
No special API: it is arithmetic on the scroll position. Give rows a known height and read scrollTop on every scroll.
const first = Math.floor(scrollTop / ROW_H);const count = Math.ceil(viewportHeight / ROW_H);const start = first - overscan;const end = first + count + overscan;const slice = items.slice(start, end); // the only mounted rowsRender slice between two spacer divs so row positions and the scrollbar stay correct:
const padTop = start * ROW_H;const padBottom = (total - end) * ROW_H;padTop + slice + padBottom always equals total * ROW_H (440,000px here), so the container is the full height it would be with every row present. Throttle the scroll handler with requestAnimationFrame. Overscan is the few extra rows each side (2 to 5) that keep a fast flick from flashing blank.
Fixed versus variable height
Fixed height is trivial: every offset is index * ROW_H. Variable height must be measured: render with an estimate, measure the real height after layout, cache it by index, and anchor the scroll position so a re-measured row does not make the list jump.
Trade-offs
You take back behaviors the browser handled for free:
- Ctrl or Cmd + F only finds mounted rows.
- Linking or scrolling to an off-screen row needs manual offset math.
- Keep list semantics intact and do not strand focus on an unmounted row.
- Drag and drop reorders by data, since the target may be unmounted.
Reach for a library (react-window, @tanstack/react-virtual, react-virtuoso); hand-roll only to learn or customize.
Why interviewers ask this
"The list could have thousands of items" is a standard scaling turn, and virtualization is the expected answer. It shows you know rendering cost scales with DOM size, not screen size. It recurs in feed, chat, table, and board questions.