SayUI
Content & display

Virtual List / Windowing

Render only the visible window of a long list and recycle nodes as the user scrolls.

Also known as virtual scroll · windowed list · recycled list

Demo · not production-ready code

Prompt for AI

Pick a stack, copy a ready prompt, paste into Cursor / Claude / ChatGPT.

Your stack

Shapes the prompt you copy

React + Tailwind + shadcn/ui · EN

Stack: React + Tailwind + shadcn/ui. Use React with Tailwind CSS and shadcn/ui patterns (Radix-based primitives, cn(), class-first styling).

Task: implement "Virtual List / Windowing".

Virtualize the order list for up to 10k rows: render the visible window plus ~5 rows of overscan, a spacer for true scroll height, stable data ids as keys. Prefer fixed row height first; measure if heights vary. Skip virtualization under a few hundred rows.

Anatomy:
- viewport / window: The rows actually mounted.
- spacer / total size: Keeps the scrollbar honest for the full dataset.
- overscan: Extra rows above/below so fast scrolls don’t flash empty.
- recycling: DOM nodes leave the window and host new data.

Preferred API / pattern: `react-window / @tanstack/virtual / virtua`

Keep scope minimal: only this UI pattern, match existing project style.

Acceptance checks

  • Avoid: Virtualizing dozens of rows
  • Avoid: Variable heights assumed fixed
  • Avoid: Fast scroll white gaps
  • Avoid: Keys are array indexes
  • Avoid: Forgetting Ctrl/Cmd+F is broken

In plain wordsHow people search for it

a huge list that still scrolls smooth because it only draws what’s on screenten thousand rows without melting the browserrecycling row DOM as I scroll instead of mounting everything

AnatomyOpen for part names

viewport / window
The rows actually mounted.
spacer / total size
Keeps the scrollbar honest for the full dataset.
overscan
Extra rows above/below so fast scrolls don’t flash empty.
recycling
DOM nodes leave the window and host new data.

How to write itOpen for stack patterns

Web (HTML/CSS)windowing libs / content-visibility: auto
React + Tailwind + shadcn/uireact-window / @tanstack/virtual / virtua
SwiftUILazyVStack / List (lazy by default)
Ant Designvirtual prop on Table/List / rc-virtual-list

Notes

Not a widget—a strategy. DOM count kills long lists; windowing turns 10k rows into ~20. Cost: in-page find won’t see unmounted rows, a11y trees are partial, variable heights get hard. Don’t virtualize a 40-row table—that’s over-engineering.

Common mistakesHumans and models trip here

  • Virtualizing dozens of rows: complexity with no payoff.
  • Variable heights assumed fixed: scrollbar jumps and hit targets lie.
  • Fast scroll white gaps: raise overscan and skeleton placeholders.
  • Keys are array indexes: recycled rows keep the wrong checkbox state—use ids.
  • Forgetting Ctrl/Cmd+F is broken: ship an explicit search field.

More failure symptoms on AI broke it.

Related patterns

Spotted a wrong name or missing pattern?

Message on X