Skip to content

UI Virtualization Catalog ​

How UI frameworks render a viewport onto a data set far larger than it — list virtualization, container recycling, builder delegates, clippers and the model protocols underneath them.

This survey exists to inform one decision: how hue's DSV data browser should scroll a multi-thousand-row grid built on sparkles:ui, a canvas-first immediate-mode toolkit. It complements three neighbouring catalogs — UI Layout (how widgets get sizes), UI backend seam (how a display list reaches a device) and TUI Libraries (terminal rendering models) — none of which covers the viewport-versus-data-size axis.

Last reviewed: August 30, 2026

The questions this survey answers ​

  1. Is clipping enough, and if not, why not? → Dear ImGui, which answers it in its own header.
  2. What do immediate-mode toolkits do, given that they rebuild everything every frame? → Dear ImGui, egui, Gio
  3. What does recycling buy, and what does it cost? → Qt Quick, GTK 4, WPF / Avalonia, VS Code
  4. How does a scrollbar describe content that was never measured? → concepts § virtual extent, Gio, egui
  5. What breaks when a view no longer contains every row? → concepts § what breaks — identity, focus, accessibility, hit testing
  6. What does a terminal change about the problem? → Textual, Ratatui
  7. Where does sparkles stand, measured rather than guessed? → sparkles baseline
  8. So what should sparkles do? → comparison

Master catalog ​

SubjectLanguageModeMechanismModel protocolRecyclesLink
Dear ImGuiC++immediateImGuiListClipper index range✗ (caller's loop)✗→
eguiRustimmediateScrollArea::show_rows(Range)✗ (closure)✗→
GioGoimmediatelayout.List + ListElement builder✗ (closure)✗→
RatatuiRustimmediate (TUI)ListState::offset + bounded walk✗ (owns a Vec)✗→
TextualPythonretained (TUI)render_line(y) / render_lines(crop)subclass-defined✗→
FlutterDartretainedslivers + SliverChildBuilderDelegatebuilderelements→
GTK 4CretainedGListModel + GtkListItemFactoryGListModelwidgets→
Qt QuickC++/QMLretainedListView + reuseItems poolQAbstractItemModeldelegates→
WPF / AvaloniaC#retainedVirtualizingStackPanelItemsSourcecontainers→
VS CodeTypeScriptretainedrange diff + RowCache + RangeMapIListVirtualDelegateDOM rows→
SlintRustretainedRepeater::ensure_updated_listviewModelinstances→
sparkles (hue DSV)DimmediateDsvWindow (DSN4) + DsvModel (DSN7)retained model✗→

Taxonomy ​

By what the window bounds ​

BoundsSubjects
Paint and measure onlyRatatui
Build, layout, paintWPF / Avalonia (default), VS Code
…and data accessDear ImGui, egui, Gio, Textual, Flutter, GTK 4, Qt Quick, Slint, sparkles

By how the visible range is computed ​

StrategyRandom accessVariable sizesSubjects
Division by a uniform sizeO(1)✗Dear ImGui, egui, Slint, sparkles
Walk from an index anchorrelative only✓Gio, Ratatui, Flutter, GTK 4, Qt Quick, WPF / Avalonia
Prefix sums over declared sizesO(log N)✓VS Code
Compositor-resolved linesO(1)n/aTextual

By how the scroll extent is known ​

StrategySubjects
Declared (exact, no measurement)egui, Textual, Slint, VS Code, Dear ImGui, sparkles
Estimated from measured itemsGio, GTK 4, Qt Quick, WPF / Avalonia
Progressive (exact where visited)Flutter

By setup/bind split ​

FormSubjects
Explicit two-phase APIGTK 4 (setup/bind), VS Code (renderTemplate/renderElement), Slint (init/update)
Split across object kindsFlutter (widget vs element)
Implicit, via a pool lifecycleQt Quick (pooled/reused), WPF / Avalonia
None — rebuild, preserve identity separatelyDear ImGui, egui, Gio, Ratatui, sparkles

Milestones ​

YearEvent
1996Windows LVS_OWNERDATA — the Win32 "virtual list view", a callback per visible item
2006WPF ships VirtualizingStackPanel with VirtualizationMode.Standard
2008WPF 3.5 SP1 adds VirtualizationMode.Recycling and VirtualizationCacheLength
2009Qt Quick 1.0 ListView instantiates only visible delegates
2014Android RecyclerView makes "recycling" the mainstream name for the idea
2015Dear ImGui gains ImGuiListClipper (evolving out of the earlier CalcListClipping)
2017Flutter's sliver protocol and ListView.builder
2020Qt 5.15 adds ListView.reuseItems — recycling, opt-in
2020GTK 4 ships GtkListView / GtkListItemFactory, retiring GtkTreeView
2026sparkles DSN4 — hue's DSV grid renders a row window, then DSN7 retains the model it is a window onto (baseline)

NOTE

Dates before 2020 are from release history rather than from the pinned trees this survey reads; treat them as orientation, not as citations.

Reading paths ​

"I want the short version." → comparison § the consensus, then comparison § what this means for sparkles.

"I'm designing virtualization for an immediate-mode toolkit." → concepts → Dear ImGui → egui → Gio → sparkles baseline → comparison.

"I want to know whether to recycle." → Qt Quick (the hazards, stated by the vendor) → GTK 4 (the setup/bind split) → VS Code (the minimal range diff) → comparison § architectural trade-offs.

"My scrollbar is wrong." → concepts § virtual extent → Gio (estimation, honestly) → VS Code (prefix sums, exactly).

"I'm doing this in a terminal." → Textual → Ratatui → sparkles baseline.

Sources ​

Every subject page cites the upstream tree it was read from, pinned to a commit. The sparkles figures come from a phase-decomposition benchmark in apps/hue/src/dsv_bench.d; see the baseline.