Horizontal and Responsive Lists
Set orientation="horizontal" for an LTR horizontal list. The same prop can change at runtime: the component clears measurements from the old axis and restores the same keyed item at its logical viewport position.
Horizontal is the deterministic first render. Choose auto to switch at the 640px breakpoint.
<script lang="ts">
import VirtualList from '@humanspeak/svelte-virtual-list'
let orientation = $state<'vertical' | 'horizontal'>('horizontal')
$effect(() => {
const query = matchMedia('(max-width: 640px)')
const update = () => (orientation = query.matches ? 'horizontal' : 'vertical')
update()
query.addEventListener('change', update)
return () => query.removeEventListener('change', update)
})
</script>
<VirtualList {items} itemKey={(item) => item.id} {orientation}>
{#snippet renderItem(item)}<article>{item.title}</article>{/snippet}
</VirtualList><script lang="ts">
import VirtualList from '@humanspeak/svelte-virtual-list'
let orientation = $state<'vertical' | 'horizontal'>('horizontal')
$effect(() => {
const query = matchMedia('(max-width: 640px)')
const update = () => (orientation = query.matches ? 'horizontal' : 'vertical')
update()
query.addEventListener('change', update)
return () => query.removeEventListener('change', update)
})
</script>
<VirtualList {items} itemKey={(item) => item.id} {orientation}>
{#snippet renderItem(item)}<article>{item.title}</article>{/snippet}
</VirtualList>Sizing and migration
defaultEstimatedItemSizeis the axis-neutral estimate and takes precedence over the compatibility aliasdefaultEstimatedItemHeightwhen both are supplied.- Items are measured along the active axis, so dynamic widths work like dynamic heights. Axis changes discard incompatible measurements.
itemKeyis strongly recommended when items can be inserted, removed, reordered, or retained across a breakpoint.- Existing vertical lists do not need changes;
orientationdefaults tovertical.
Scrolling, loading, and keys
scroll() alignment values start, end, nearest, and center are axis-neutral. The older top and bottom values remain vertical compatibility aliases. scrollToOffset() also follows the active axis. Infinite loading triggers at the logical end in either orientation.
When a horizontal viewport is focused, Left/Right move by 40px, Home/End go to the logical edges, and Page Up/Page Down plus Space/Shift+Space move by one viewport page with a 40px overlap. Up/Down remain available to the page and interactive descendants keep their native key behavior.
Horizontal mode is LTR-only in this release. RTL normalization is not yet supported.