yew-virtual 0.2.0

A headless virtualization engine for the Yew framework, equivalent to TanStack Virtual
Documentation

yew-virtual

CI Crates.io License

A headless virtualization engine for Yew applications, aligned in spirit with TanStack Virtual. It is built for very large lists and grids in WebAssembly: you keep full control of markup and styling while the engine computes visible ranges, overscan, and scroll alignment.

Live demo

  • Tailwind example — vertical and horizontal virtual lists with Tailwind, live stats, and copy aimed at real integrations.

Overview

yew-virtual splits a headless core (Virtualizer, options, and measurement math) from Yew hooks (use_virtualizer, use_window_virtualizer) that attach passive scroll listeners and resize observers. Use the core alone for tests or non-DOM simulations, or pair hooks with your own absolutely positioned rows or columns.

  • Headless engine — Range extraction, overscan, padding, gap, dynamic measurement, scroll-to-index.
  • Container and window hooks — Ref-based scroll container or document-level scroll.
  • Sizing modes — Fixed, estimated, and dynamic strategies with optional per-item observers.
  • Safe Rust — No unsafe, unwrap(), or expect() in the library crate.

Features

Area Capabilities
Layout Vertical and horizontal axes, RTL-aware horizontal scrollLeft
Sizing Fixed, Estimated, Dynamic; optional runtime measurement
Scrolling Overscan; programmatic scroll-to-index (Start / Center / End / Auto)
Spacing Gap between items; padding at start and end
Hooks Passive scroll listeners; ResizeObserver on the scroll container
Quality Explicit error types; integration tests and CI coverage gate

Installation

[dependencies]
yew = { version = "0.21", features = ["csr"] }
yew-virtual = "0.1"

Enable yew’s csr feature for browser (WASM) apps, or ssr / hydration when you follow Yew’s server-side rendering setup. yew-virtual does not define its own csr / ssr flags.

Quick start

Core engine (no DOM)

use yew_virtual::core::virtualizer::Virtualizer;
use yew_virtual::core::virtualizer_options::VirtualizerOptions;
use yew_virtual::core::item_size_mode::ItemSizeMode;

let options = VirtualizerOptions {
    item_count: 100_000,
    item_size_mode: ItemSizeMode::Fixed(50.0),
    container_size: Some(600.0),
    overscan: 5,
    ..VirtualizerOptions::default()
};

let mut virt = Virtualizer::new(options).expect("valid config");
virt.update_scroll_offset(500.0);

for item in virt.get_virtual_items() {
    println!("Index: {}, Offset: {}px, Size: {}px", item.index, item.start, item.size);
}

With Yew hooks (WASM)

use yew::prelude::*;
use yew_virtual::hooks::use_virtualizer::use_virtualizer;
use yew_virtual::core::virtualizer_options::VirtualizerOptions;
use yew_virtual::core::item_size_mode::ItemSizeMode;

#[function_component(VirtualList)]
fn virtual_list() -> Html {
    let options = VirtualizerOptions {
        item_count: 100_000,
        item_size_mode: ItemSizeMode::Fixed(50.0),
        overscan: 5,
        ..VirtualizerOptions::default()
    };

    let (handle, container_ref) = use_virtualizer(options);

    html! {
        <div ref={container_ref} style="height: 600px; overflow-y: auto;">
            <div style={format!("height: {}px; position: relative;", handle.total_size())}>
                { for handle.get_virtual_items().iter().map(|item| html! {
                    <div
                        key={item.index}
                        style={format!(
                            "position: absolute; top: 0; left: 0; right: 0; height: {}px; transform: translateY({}px);",
                            item.size, item.start
                        )}
                    >
                        { format!("Item {}", item.index) }
                    </div>
                })}
            </div>
        </div>
    }
}

Scroll alignment

When using scroll_to_index, four alignment modes are available:

Alignment Behavior
Start Item aligned to the viewport start
Center Item centered in the viewport
End Item aligned to the viewport end
Auto Minimal scroll so the item becomes visible

Item size modes

Mode Description
Fixed(f64) Uniform item size; no measurement
Estimated(f64) Initial guess; refined when measured
Dynamic(f64) Fallback size; measured at runtime

Running the example

The Tailwind demo uses Trunk:

cargo install trunk
cd examples/tailwind-virtual-list
trunk serve

Running tests

cargo test -p yew-virtual

New tests should follow TEST_RULES.md. CI runs cargo-tarpaulin on the yew-virtual package with --fail-under 90 and uploads results to Codecov.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md before opening a pull request.

License

Distributed under the MIT license.