Vertical Dynamic Body
Native window scrolling with variable item heights
This example uses the main browser window for scrolling 1,000 dynamic items. Sizes are automatically detected via ResizeObserver.
Scrollable Header
This header and fixed height items scroll with the page
#0
Body Scroll Dynamic Item 0 (Height: 50px)
#1
Body Scroll Dynamic Item 1 (Height: 100px)
#2
Body Scroll Dynamic Item 2 (Height: 50px)
#3
Body Scroll Dynamic Item 3 (Height: 100px)
#4
Body Scroll Dynamic Item 4 (Height: 50px)
Page Footer
End of the 1,000 dynamic items list
<script setup lang="ts">
import type { Ref } from 'vue';
import { VirtualScroll } from '@pdanpdan/virtual-scroll';
import { computed, inject, onMounted, ref } from 'vue';
import ExampleContainer from '#/components/ExampleContainer.vue';
import ScrollControls from '#/components/ScrollControls.vue';
import ScrollStatus from '#/components/ScrollStatus.vue';
import { useExampleScroll } from '#/lib/useExampleScroll';
import { html as highlightedCode } from './+Page.vue?highlight';
const scrollContainer = ref<Window | null>(null);
onMounted(() => {
scrollContainer.value = window;
});
const itemCount = ref(1000);
const itemSize = ref(50); // Approximate base size
const bufferBefore = ref(5);
const bufferAfter = ref(5);
// Use a deterministic function for item size
// Pattern: base, base*2, base, base*2, ...
const itemSizeFn = computed(() => {
const base = itemSize.value;
return (item: unknown, index: number) => index % 2 === 0 ? base : base * 2;
});
const items = computed(() => Array.from({ length: itemCount.value }, (_, i) => ({
id: i,
text: `Body Scroll Dynamic Item ${ i } (Height: ${ itemSizeFn.value(null, i) }px)`,
})));
const {
virtualScrollRef,
scrollDetails,
onScroll,
handleScrollToIndex,
handleScrollToOffset,
} = useExampleScroll();
const debugMode = inject<Ref<boolean>>('debugMode', ref(false));
</script>
<template>
<ExampleContainer height="auto" :code="highlightedCode">
<template #title>
<span class="example-title example-title--group-2">Vertical Dynamic Body</span>
</template>
<template #description>
This example uses the main browser window for scrolling {{ itemCount.toLocaleString() }} dynamic items. Sizes are automatically detected via <strong>ResizeObserver</strong>.
</template>
<template #icon>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="example-icon example-icon--group-2"
>
<path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25" />
</svg>
</template>
<template #subtitle>
Native window scrolling with variable item heights
</template>
<template #controls>
<ScrollStatus :scroll-details="scrollDetails" direction="vertical" />
<ScrollControls
v-model:item-count="itemCount"
v-model:item-size="itemSize"
v-model:buffer-before="bufferBefore"
v-model:buffer-after="bufferAfter"
direction="vertical"
@scroll-to-index="handleScrollToIndex"
@scroll-to-offset="handleScrollToOffset"
@refresh="virtualScrollRef?.refresh()"
/>
</template>
<VirtualScroll
ref="virtualScrollRef"
:debug="debugMode"
class="example-container"
:items="items"
:container="scrollContainer"
:buffer-before="bufferBefore"
:buffer-after="bufferAfter"
aria-label="Dynamic height body scroll list"
@scroll="onScroll"
>
<template #header>
<div class="example-body-header">
<h2>Scrollable Header</h2>
<p>This header and fixed height items scroll with the page</p>
</div>
</template>
<template #item="{ item, index }">
<div class="example-vertical-item py-4">
<span class="example-badge me-8">#{{ index }}</span>
<div class="font-bold" :style="{ minBlockSize: `${ itemSizeFn(null, index) }px` }">{{ item.text }}</div>
</div>
</template>
<template #footer>
<div class="example-body-footer">
<h2>Page Footer</h2>
<p>End of the {{ itemCount.toLocaleString() }} dynamic items list</p>
</div>
</template>
</VirtualScroll>
</ExampleContainer>
</template>
- Scroll Status
- Directionvertical
- Current Item #-
- Rendered Range #0:0
- Total Size (px)0h
- Viewport Size (px)0h
- Scroll Offset (px)0y
- Controls