Scroll Methods

You can programmatically scroll to any item in the list using the scroll method. This is useful for jump-to-item navigation, search results, and more.

Interactive Demo

file · ScrollToItemExample.svelte mode · live running open source
● ready
Item 0 first
Item 1 scroll target
Item 2 scroll target
Item 3 scroll target
Item 4 scroll target
Item 5 scroll target
Item 6 scroll target
Item 7 scroll target
Item 8 scroll target
Item 9 scroll target
Item 10 scroll target
Item 11 scroll target
Item 12 scroll target
Item 13 scroll target
Item 14 scroll target
Item 15 scroll target
Item 16 scroll target
Item 17 scroll target
Item 18 scroll target
Item 19 scroll target
Item 20 scroll target
target · 5000
align · auto
range · 0-0
dom rows · 0
dom nodes · 0

Basic Usage

To use the scroll method, bind a reference to the VirtualList component:

<script lang="ts">
    import VirtualList from '@humanspeak/svelte-virtual-list'

    let listRef

    const items = Array.from({ length: 10000 }, (_, i) => ({
        id: i,
        text: `Item ${i}`
    }))

    function goToItem5000() {
        listRef.scroll({
            index: 5000,
            smoothScroll: true,
            align: 'auto'
        })
    }
</script>

<button onclick={goToItem5000}>
    Scroll to item 5000
</button>

<VirtualList {items} bind:this={listRef}>
    {#snippet renderItem(item)}
        <div>{item.text}</div>
    {/snippet}
</VirtualList>
<script lang="ts">
    import VirtualList from '@humanspeak/svelte-virtual-list'

    let listRef

    const items = Array.from({ length: 10000 }, (_, i) => ({
        id: i,
        text: `Item ${i}`
    }))

    function goToItem5000() {
        listRef.scroll({
            index: 5000,
            smoothScroll: true,
            align: 'auto'
        })
    }
</script>

<button onclick={goToItem5000}>
    Scroll to item 5000
</button>

<VirtualList {items} bind:this={listRef}>
    {#snippet renderItem(item)}
        <div>{item.text}</div>
    {/snippet}
</VirtualList>

API Reference

scroll(options)

Scrolls the list to bring a specific item into view.

scroll(options: {
    index: number
    smoothScroll?: boolean
    shouldThrowOnBounds?: boolean
    align?: 'auto' | 'top' | 'bottom' | 'nearest' | 'center'
}): Promise<void>
scroll(options: {
    index: number
    smoothScroll?: boolean
    shouldThrowOnBounds?: boolean
    align?: 'auto' | 'top' | 'bottom' | 'nearest' | 'center'
}): Promise<void>

Options

OptionTypeDefaultDescription
indexnumberRequiredThe item index to scroll to (0-based)
smoothScrollbooleantrueUse smooth scrolling animation
shouldThrowOnBoundsbooleantrueThrow error if index is out of bounds
alignstring'auto'Where to align the item in the viewport

Alignment Options

  • 'auto' (default) - Only scroll if the item is not visible. Aligns to top or bottom as appropriate.
  • 'top' - Always align the item to the top of the viewport.
  • 'bottom' - Always align the item to the bottom of the viewport.
  • 'nearest' - Scroll as little as possible to bring the item into view (like native scrollIntoView({ block: 'nearest' })).
  • 'center' - Center the item vertically in the viewport, clamped at the list edges. Great for focusing a search result or highlighted item so it lands in the middle of the view.

Examples

Scroll to specific index

<button onclick={() => listRef.scroll({ index: 500 })}>
    Go to item 500
</button>
<button onclick={() => listRef.scroll({ index: 500 })}>
    Go to item 500
</button>

Scroll without animation

<button onclick={() => listRef.scroll({ index: 500, smoothScroll: false })}>
    Jump to item 500 (instant)
</button>
<button onclick={() => listRef.scroll({ index: 500, smoothScroll: false })}>
    Jump to item 500 (instant)
</button>

Always align to top

<button onclick={() => listRef.scroll({ index: 500, align: 'top' })}>
    Scroll to item 500 (top aligned)
</button>
<button onclick={() => listRef.scroll({ index: 500, align: 'top' })}>
    Scroll to item 500 (top aligned)
</button>

Minimal scrolling

<button onclick={() => listRef.scroll({ index: 500, align: 'nearest' })}>
    Scroll to item 500 (nearest)
</button>
<button onclick={() => listRef.scroll({ index: 500, align: 'nearest' })}>
    Scroll to item 500 (nearest)
</button>

Center the item in the viewport

<button onclick={() => listRef.scroll({ index: 500, align: 'center' })}>
    Scroll to item 500 (centered)
</button>
<button onclick={() => listRef.scroll({ index: 500, align: 'center' })}>
    Scroll to item 500 (centered)
</button>

scrollToOffset(options)

Scrolls the viewport to a raw pixel offset instead of an item index. This complements scroll() (which is index-based) and is ideal for restoring a persisted scroll position after navigation.

scrollToOffset(options: {
    offset: number
    smoothScroll?: boolean
}): Promise<void>
scrollToOffset(options: {
    offset: number
    smoothScroll?: boolean
}): Promise<void>

The offset is clamped to the list’s valid scroll range, so values beyond the end simply settle at the bottom. The returned promise resolves once scrolling has visually finished.

Options

OptionTypeDefaultDescription
offsetnumberRequiredRaw vertical scroll offset in pixels
smoothScrollbooleantrueUse smooth scrolling animation

Example

<script lang="ts">
    import VirtualList from '@humanspeak/svelte-virtual-list'

    let listRef

    // e.g. a value read back from sessionStorage
    const savedOffset = 12345

    function restoreScrollPosition() {
        listRef.scrollToOffset({ offset: savedOffset, smoothScroll: false })
    }
</script>

<button onclick={restoreScrollPosition}>
    Restore scroll position
</button>

<VirtualList {items} bind:this={listRef}>
    {#snippet renderItem(item)}
        <div>{item.text}</div>
    {/snippet}
</VirtualList>
<script lang="ts">
    import VirtualList from '@humanspeak/svelte-virtual-list'

    let listRef

    // e.g. a value read back from sessionStorage
    const savedOffset = 12345

    function restoreScrollPosition() {
        listRef.scrollToOffset({ offset: savedOffset, smoothScroll: false })
    }
</script>

<button onclick={restoreScrollPosition}>
    Restore scroll position
</button>

<VirtualList {items} bind:this={listRef}>
    {#snippet renderItem(item)}
        <div>{item.text}</div>
    {/snippet}
</VirtualList>

TypeScript

For full type safety, you can type the ref:

type ListRef = {
    scroll: (options: {
        index: number
        smoothScroll?: boolean
        shouldThrowOnBounds?: boolean
        align?: 'auto' | 'top' | 'bottom' | 'nearest' | 'center'
    }) => Promise<void>
    scrollToOffset: (options: {
        offset: number
        smoothScroll?: boolean
    }) => Promise<void>
}

let listRef: ListRef | undefined = $state(undefined)
type ListRef = {
    scroll: (options: {
        index: number
        smoothScroll?: boolean
        shouldThrowOnBounds?: boolean
        align?: 'auto' | 'top' | 'bottom' | 'nearest' | 'center'
    }) => Promise<void>
    scrollToOffset: (options: {
        offset: number
        smoothScroll?: boolean
    }) => Promise<void>
}

let listRef: ListRef | undefined = $state(undefined)

Or import the types from the package:

import type {
    SvelteVirtualListScrollOptions,
    SvelteVirtualListScrollAlign
} from '@humanspeak/svelte-virtual-list'
import type {
    SvelteVirtualListScrollOptions,
    SvelteVirtualListScrollAlign
} from '@humanspeak/svelte-virtual-list'