A high-performance virtual list component for Svelte 5 applications that efficiently renders large datasets with minimal memory usage.
- π Dynamic item height handling - no fixed height required
- π Bi-directional scrolling support (top-to-bottom and bottom-to-top)
- π Automatic resize handling for dynamic content
- π TypeScript support with full type safety
- π SSR compatible with hydration support
- β¨ Svelte 5 runes and snippets support
- π¨ Customizable styling with class props
- π Debug mode for development
- π― Smooth scrolling with configurable buffer zones
- π§ Memory-optimized for 10k+ items
- π§ͺ Comprehensive test coverage (vitest and playwright)
- π Progressive initialization for large datasets
- πΉοΈ Programmatic scrolling with
scroll
You can now programmatically scroll to any item in the list using the scroll
method. This is useful for chat apps, jump-to-item navigation, and more. You can check the usage in src/routes/tests/scroll
. Thank you for the feature request!
<script lang="ts">
import SvelteVirtualList from '@humanspeak/svelte-virtual-list'
let listRef
const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Item ${i}` }))
function goToItem5000() {
// Scroll to item 5000 with smooth scrolling and auto alignment
listRef.scroll({ index: 5000, smoothScroll: true, align: 'auto' })
}
</script>
<button on:click={goToItem5000}> Scroll to item 5000 </button>
<SvelteVirtualList {items} bind:this={listRef}>
{#snippet renderItem(item)}
<div>{item.text}</div>
{/snippet}
</SvelteVirtualList>
scroll(options: { index: number; smoothScroll?: boolean; shouldThrowOnBounds?: boolean; align?: 'auto' | 'top' | 'bottom' })
index
: The item index to scroll to (0-based)smoothScroll
: If true, uses smooth scrolling (default: true)shouldThrowOnBounds
: If true, throws if index is out of bounds (default: true)align
: Where to align the item in the viewport.'auto'
(default) scrolls only if the item is out of view, aligning to top or bottom as needed.'top'
always aligns to the top,'bottom'
always aligns to the bottom.
npm install @humanspeak/svelte-virtual-list
<script lang="ts">
import SvelteVirtualList from '@humanspeak/svelte-virtual-list'
const items = Array.from({ length: 1000 }, (_, i) => ({
id: i,
text: `Item ${i}`
}))
</script>
<SvelteVirtualList {items}>
{#snippet renderItem(item)}
<div>{item.text}</div>
{/snippet}
</SvelteVirtualList>
<script lang="ts">
import SvelteVirtualList from '@humanspeak/svelte-virtual-list'
type Message = {
id: number
text: string
timestamp: Date
}
const messages: Message[] = Array.from({ length: 100 }, (_, i) => ({
id: i,
text: `Message ${i}`,
timestamp: new Date()
}))
</script>
<div style="height: 500px;">
<SvelteVirtualList items={messages} mode="bottomToTop" debug>
{#snippet renderItem(message)}
<div class="message-container">
<p>{message.text}</p>
<span class="timestamp">
{message.timestamp.toLocaleString()}
</span>
</div>
{/snippet}
</SvelteVirtualList>
</div>
Prop | Type | Default | Description |
---|---|---|---|
items |
T[] |
Required | Array of items to render |
defaultItemHeight |
number |
40 |
Initial height for items before measurement |
mode |
'topToBottom' | 'bottomToTop' |
'topToBottom' |
Scroll direction |
bufferSize |
number |
20 |
Number of items to render outside viewport |
debug |
boolean |
false |
Enable debug logging and visualizations |
containerClass |
string |
'' |
Class for outer container |
viewportClass |
string |
'' |
Class for scrollable viewport |
contentClass |
string |
'' |
Class for content wrapper |
itemsClass |
string |
'' |
Class for items container |
- The
bufferSize
prop affects memory usage and scroll smoothness - Items are measured and cached for optimal performance
- Dynamic height calculations happen automatically
- Resize observers handle container/content changes
- Virtual DOM updates are batched for efficiency
MIT Β© Humanspeak, Inc.
Made with β₯ by Humanspeak