$npx -y skills add skilld-dev/vue-ecosystem-skills --skill tanstack-vue-virtual-skilldHeadless UI for virtualizing scrollable elements in Vue. ALWAYS use when writing code importing \"@tanstack/vue-virtual\". Consult for debugging, best practices, or modifying @tanstack/vue-virtual, tanstack/vue-virtual, tanstack vue-virtual, tanstack vue virtual, virtual.
| 1 | # TanStack/virtual `@tanstack/vue-virtual@3.13.24` |
| 2 | **Tags:** beta: 3.0.0-beta.68, latest: 3.13.24 |
| 3 | |
| 4 | **References:** [Docs](./references/docs/_INDEX.md) |
| 5 | ## API Changes |
| 6 | |
| 7 | This section documents version-specific API changes — prioritize recent major/minor releases. |
| 8 | |
| 9 | - BREAKING: `useVirtualizer` — replaces `useVirtual` in v3 migration; older positional arguments or v2 option names are no longer supported [source](./references/docs/framework/vue/vue-virtual.md) |
| 10 | |
| 11 | - BREAKING: `Ref<Virtualizer>` return type — v3 `useVirtualizer` returns a Vue `Ref` instead of a raw object; instance methods must be accessed via `.value` (e.g., `rowVirtualizer.value.getVirtualItems()`) |
| 12 | |
| 13 | - BREAKING: `count` — replaces `size` option in v3 migration; using `size` will result in zero items being virtualized [source](./references/docs/api/virtualizer.md) |
| 14 | |
| 15 | - BREAKING: `getScrollElement` — replaces `parentRef` option in v3 migration; must be a function that returns the scrollable element or `null` [source](./references/docs/api/virtualizer.md) |
| 16 | |
| 17 | - BREAKING: `measureElement` — replaces `measureRef` pattern from v2; you must now pass `virtualizer.value.measureElement` to the `ref` attribute and set `data-index` on the element [source](./references/docs/api/virtualizer.md) |
| 18 | |
| 19 | - NEW: `getTotalSize()` auto-updates — as of v3.13.13, the virtualizer automatically notifies the framework when the `count` option changes, ensuring `getTotalSize()` and the UI update correctly without manual workarounds for filtering or search [source](./references/releases/@tanstack/vue-virtual@3.13.13.md) |
| 20 | |
| 21 | - NEW: `lanes` — new in v3; allows dividing the list into multiple columns (vertical) or rows (horizontal) to support grid-like or masonry layouts [source](./references/docs/api/virtualizer.md) |
| 22 | |
| 23 | - NEW: `gap` — new in v3; specifies the spacing between items in pixels, removing the need for manual margin or padding calculations [source](./references/docs/api/virtualizer.md) |
| 24 | |
| 25 | - NEW: `useWindowVirtualizer` — specialized adapter for window-based scrolling; simplifies configuration when the browser window is the scroll container [source](./references/docs/framework/vue/vue-virtual.md) |
| 26 | |
| 27 | - NEW: `scrollMargin` — allows specifying the offset between the scroll container's start and the beginning of the virtualized list; essential for lists preceded by headers [source](./references/docs/api/virtualizer.md) |
| 28 | |
| 29 | - NEW: `isRtl` — built-in support for right-to-left language locales; inverts horizontal scrolling logic when enabled [source](./references/docs/api/virtualizer.md) |
| 30 | |
| 31 | - NEW: `useScrollendEvent` — utilizes the native `scrollend` event where available to reset `isScrolling` state, falling back to a debounced timer if disabled [source](./references/docs/api/virtualizer.md) |
| 32 | |
| 33 | - NEW: `shouldAdjustScrollPositionOnItemSizeChange` — provides fine-grained control over scroll position adjustments when dynamic items differ from their estimated size [source](./references/docs/api/virtualizer.md) |
| 34 | |
| 35 | - NEW: `useAnimationFrameWithResizeObserver` — added in v3.13.x; defers ResizeObserver measurement processing to the next animation frame to batch DOM mutations [source](./references/docs/api/virtualizer.md) |
| 36 | |
| 37 | **Also changed:** `isScrollingResetDelay` new in v3 · `rangeExtractor` now receives `Range` object · `VirtualItem` adds `lane` property · `resizeItem` method for manual size overrides · `enabled` option to pause observers |
| 38 | |
| 39 | ## Best Practices |
| 40 | |
| 41 | - Account for `scrollMargin` in absolute positioning — when using a shared scroll container with static headers, subtract the margin from the item's start position to maintain correct layout [source](./references/docs/api/virtualizer.md) |
| 42 | |
| 43 | ```vue |
| 44 | <script setup> |
| 45 | const rowVirtualizer = useVirtualizer({ |
| 46 | count: 1000, |
| 47 | scrollMargin: 100, // Height of header |
| 48 | // ... |
| 49 | }) |
| 50 | </script> |
| 51 | |
| 52 | <template> |
| 53 | <div v-for="item in rowVirtualizer.getVirtualItems()" :key="item.key" |
| 54 | :style="{ |
| 55 | transform: `translateY(${item.start - rowVirtualizer.options.scrollMargin}px)` |
| 56 | }" |
| 57 | > |
| 58 | {{ item.index }} |
| 59 | </div> |
| 60 | </template> |
| 61 | ``` |
| 62 | |
| 63 | - Overestimate `estimateSize` for dynamic elements — providing a "maximum likely" size prevents the scrollbar from jumping and items from "resetting" their position when scrolling upwards into unmeasured territory [source](./references/docs/api/virtualizer.md) |
| 64 | |
| 65 | - Implement `shouldAdjustScrollPositionOnItemSizeChange` for chat/messaging UIs — use this callback to control scroll adjustments when prepending items, preventing visual jumps as new elements are measured [source](./references/docs/api/virtualizer.md) |
| 66 | |
| 67 | - Attach `data-index` when |