A high-performance virtual list component for Svelte 5 applications that efficiently renders large datasets with minimal memory usage.
scrollYou 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' | 'nearest' })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): Only scroll if not visible, align to top or bottom as appropriate'top': Always align to the top'bottom': Always align to the bottom'nearest': Scroll as little as possible to bring the item into view (like native scrollIntoView({ block: 'nearest' }))<button on:click={() => listRef.scroll({ index: 5000, align: 'nearest' })}>
Scroll to item 5000 (nearest)
</button>
# Using npm
npm install @humanspeak/svelte-virtual-list
# Using pnpm (recommended)
pnpm add @humanspeak/svelte-virtual-list
# Using yarn
yarn add @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>
Use mode="bottomToTop" for chat-like lists anchored to the bottom. Programmatic scrolling uses the same API as top-to-bottom lists:
<script lang="ts">
import SvelteVirtualList from '@humanspeak/svelte-virtual-list'
let listRef
const messages = Array.from({ length: 2000 }, (_, i) => ({ id: i, text: `Msg ${i}` }))
</script>
<SvelteVirtualList items={messages} mode="bottomToTop" bind:this={listRef} />
<button on:click={() => listRef.scroll({ index: messages.length - 1, align: 'bottom' })}>
Jump to latest
</button>
| Prop | Type | Default | Description |
|---|---|---|---|
items |
T[] |
Required | Array of items to render |
defaultEstimatedItemHeight |
number |
40 |
Initial height estimate used until items are measured |
mode |
'topToBottom' | 'bottomToTop' |
'topToBottom' |
Scroll direction and anchoring behavior |
bufferSize |
number |
20 |
Number of items rendered outside the 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 |
testId |
string |
'' |
Base test id used in internal test hooks (useful for E2E/tests and debugging) |
# Run unit tests with coverage
pnpm test
# Run specific test files
pnpm vitest src/lib/utils/throttle.test.ts
# Install Playwright browsers (one-time setup)
npx playwright install
# Run all e2e tests
pnpm run test:e2e
# Run specific e2e test
npx playwright test tests/docs-visit.spec.ts --project=chromium
# Debug mode
npx playwright test --debug
# Start development server
pnpm dev
# Start both package and docs
pnpm run dev:all
# Check TypeScript/Svelte
pnpm run check
# Build package
pnpm run build
# Format and lint code
pnpm run lint:fix
bufferSize prop affects memory usage and scroll smoothnessThis is a PNPM workspace with two packages:
./ - Main Svelte Virtual List component package./docs - Documentation site with live demos and examples# Install dependencies for both packages
pnpm install
# Run development servers simultaneously
pnpm run dev:all
# Build both packages
pnpm run build
# Run tests across the workspace
pnpm test:all
MIT ยฉ Humanspeak, Inc.
Made with โค๏ธ by Humanspeak