Virtualized lists render only what is on screen so long lists stay usable
Aliases: virtual list · windowing · recycled rows
What it is
When a list holds thousands of rows, making a real node for every row will collapse layout and memory. Windowed rendering builds nodes only for the slice in the viewport — plus a little buffer — and holds the rest of the scroll range with placeholder height. The user’s model remains “this is one complete list.” The implementation’s model is “only rows in the window exist.” This is why the technique exists and what the window is protecting. It is not about find-in-page, and not about whether the scrollbar tells the truth.
Why it happens
Every DOM node or native view has a fixed cost in layout, paint, events, and the accessibility tree. Cost grows linearly with row count; past a scale, frame rate drops into perceptible jank and scrolling itself becomes task failure. Virtualisation pins cost to window size: ten thousand or a hundred thousand rows, the live nodes are roughly one screen plus buffer. The buffer exists so rows about to enter the viewport are ready; otherwise each flick creates nodes on the spot. Rows outside the window still exist in data; they have no view. Completeness for the user is maintained by scroll range and row numbers; for the system it is a fiction — the assistive tree, in-page find, and print all hit “not in the window, not there.” Virtualisation is a trade of performance against completeness, not a free speedup.
Studying it
On the same dataset, compare full render with windowed render. Measure time to first screen, scroll frame rate, memory, and interaction delay after scrolling far. Independent variables: window height, buffer rows, whether row height varies. Dependent variables: dropped frames, jank reports, peak memory. Variable row height forces the window to estimate; look separately at jumps caused by estimate error. “Feels smooth” is not enough — plot frame-time distributions; a long-tail hitch is a create spike the window did not cover.
Where it stops holding
Tens of rows make virtualisation surplus; window overhead can exceed a full render. Cases that must measure or export every row (select-all copy, print) cannot live on the window alone; they need a data path that does not go through views. Server paging already limits live data; a second virtualisation layer must be clear about what each layer is protecting. On low-end devices the window must be smaller still; a large buffer will hitch.
Applying it
- Turn virtualisation on at the data scale where jank is perceptible; keep small lists fully rendered.
- Size the window to one screen plus a buffer, with more rows in the scroll direction.
- Keep row height as stable as you can, so estimated heights are not corrected into a jump on scroll-in.
- How to check: on the target device, scroll the whole long list. Frame time should lack long-tail spikes, and memory should not grow linearly with rows passed.
Related
- Within the group: E4.18.2 In-page find can fail under virtualisation · E4.18.3 The scrollbar’s position must map honestly to the real amount of data · E4.18.4 Placeholder flicker during a fast flick hurts readability
- Adjacent: E4.02 List items · E5.07 Infinite scroll
- Search terms:
virtualized list·windowing·recycle views