Virtual List
Browse thousands of rows while mounting only the visible window.

use blinc_layout::prelude::*;
pub fn virtual_list_demo() -> Div {
div().class("demo-wide").child(
blinc_layout::widgets::virtual_list::virtual_list(10_000, |index| {
div()
.class("demo-virtual-row")
.child(text(format!("Message {:05}", index + 1)))
})
.estimated_item_height(40.0)
.window_size(24)
.w_full()
.h(216.0)
.class("demo-virtual-list")
.into_div(),
)
}
Usage and properties
Browse thousands of rows while mounting only the visible window. This built-in widget is provided by blinc_layout; the polished action controls in the example use blinc_cn.
Use the installation guide to create a Blinc application. This widget is available from blinc_layout; the demo uses the same Hybrid theme as the component library. Create the fixture bindings once, and return the demo from your UI builder. Values marked Bound accept Signal/Computed sources where the API supports them; structural options configure the component at construction.
| Property | Type | Update model | This example |
|---|---|---|---|
item_count | usize | Construction | 10,000 |
item builder | Fn(usize) -> Div | Construction | Message 00001… |
estimated_item_height / window_size | f32 / usize | Construction | 40 / 24 |
Keyboard and interaction
Scroll with the wheel or trackpad. The example keeps scrolling within its own viewport.
Customizing it
Add application CSS after the default component layer. These selectors are the restyling surface for this component:
.demo-virtual-list.demo-virtual-row
Theme and component variables: --primary, --text-primary, --text-secondary, --surface, --border, --radius-default, --duration-fast, --ease-state.
Built-in themes
The Live theme control installs Blinc's own theme bundles, including their colours, focus rings, corner shapes and motion tokens.
pub fn theme_bundle_for(name: &str) -> blinc_theme::ThemeBundle {
match name {
"restrained" => blinc_theme::RestrainedTheme::bundle(),
"expressive" => blinc_theme::ExpressiveTheme::bundle(),
_ => blinc_theme::HybridTheme::bundle(),
}
.with_css(blinc_cn::cn_styles::CN_STYLES)
}Download the default widget and component stylesheets. Sample assets and licenses are available in the asset guide.
Documentation
From the canonical component guide.
The virtual_list widget efficiently renders large datasets by only creating elements for a window of visible items. Items can have variable heights — flexbox layout determines their size.
Basic Usage
use blinc::layout::widgets::virtual_list::virtual_list;
let items: Vec<String> = (0..10_000)
.map(|i| format!("Item {}", i))
.collect();
virtual_list(items.len(), move |index| {
div()
.w_full()
.p_px(8.0)
.flex_row()
.items_center()
.child(text(&items[index]).size(14.0).color(Color::WHITE))
})
.w_full()
.h(400.0)
.into_div()
Variable Height Items
Items don't need a fixed height. Flexbox handles sizing:
virtual_list(messages.len(), move |i| {
let msg = &messages[i];
div()
.w_full()
.p_px(12.0)
.flex_col()
.gap_px(4.0)
.child(text(&msg.author).size(12.0).bold().color(Color::WHITE))
.child(text(&msg.body).size(14.0).color(Color::rgba(0.8, 0.8, 0.8, 1.0)))
// Height is determined by content — short messages are small, long ones wrap
})
.w_full()
.h(600.0)
.into_div()
Configuration
virtual_list(count, builder)
.w_full() // Width
.h(400.0) // Viewport height
.bg(Color::BLACK) // Background
.rounded(8.0) // Corner radius
.gap_px(4.0) // Gap between items
.estimated_item_height(48.0) // Hint for scroll spacer (default: 40px)
.window_size(80) // Items to render at once (default: 50)
.into_div()
| Option | Default | Description |
|---|---|---|
estimated_item_height | 40.0 | Average item height estimate for scroll spacer calculation |
window_size | 50 | Number of items rendered at once |
How It Works
- The builder creates elements for the first
window_sizeitems - Flexbox layout determines each item's actual height
- A spacer div below the rendered items estimates the remaining scroll height
- The scroll container provides momentum physics scrolling
- Items use their natural flex-determined height — no fixed constraints
Platforms and version
The component API is available in Blinc 0.6.0. The Live example runs in a dedicated worker and requires a compatible GPU surface. Preview and Code remain available when Live cannot start. The canvas has a descriptive label; a full screen-reader DOM mirror is not provided. The gallery integration is based on revision e2e55c24e078.
Recordings and live demos use the default Hybrid theme with bundled Noto Sans. The recording uses a 560 × 320 logical viewport at twice that resolution. Live follows its container and actual display density. Source base revision · Exact build source · Artifact versions and checksums · Font license.