Virtual Scroller
A container component used to display content within a limited space (rows or columns). Unlike the Step Scroller, it simulates the browser's native smooth scrolling experience (stepless scrolling). It supports custom scrollbar styles or continuous scrolling via long-pressing buttons.
Basic Usage
By default, the component uses a horizontal layout and displays a customized scrollbar.
<script setup>
import { ref } from 'vue'
const list = ref(Array.from({ length: 20 }, (_, i) => i + 1))
</script>
<template>
<div style="height: 60px;">
<TuiVirtualScroller>
<div v-for="item in list" :key="item" class="item-box">
Item {{ item }}
</div>
</TuiVirtualScroller>
</div>
</template>
<style scoped>
.item-box {
padding: 0 20px;
border: 1px solid var(--tui-border-color);
display: flex;
align-items: center;
border-radius: 4px;
}
</style>Control Types
This is the core feature of the component. Through the ctrlType property, you can decide how users perform scrolling operations.
- scrollbar (Default): Displays a styled scrollbar that supports dragging.
- button: Hides the scrollbar and displays control buttons on both sides. Long-pressing the buttons enables smooth, continuous scrolling.
- none: Hides all visual controllers; supports only mouse wheel or touch swiping.
<script setup>
import { reactive } from 'vue'
const config = reactive({
type: 'scrollbar'
})
</script>
<template>
<div class="control-panel">
<TuiRadio v-model="config.type" :options="['scrollbar', 'button', 'none']" />
</div>
<div style="height: 80px; margin-top: 20px;">
<TuiVirtualScroller :ctrlType="config.type">
<div v-for="i in 15" :key="i" class="item">Element {{ i }}</div>
</TuiVirtualScroller>
</div>
</template>Button Mode Configuration
When ctrlType="button", you can further customize the behavior and appearance of the buttons.
buttonPosition: Controls the position of the buttons.
both: One on each side (Default).start: Both at the starting position.end: Both at the ending position.float: Floating above the content.buttonSize: Button dimensions (
small,default,large).scrollSpeed: Controls the scrolling speed multiplier during a button long-press.
<template>
<TuiVirtualScroller
ctrlType="button"
buttonPosition="float"
buttonSize="large"
:scrollSpeed="2"
>
</TuiVirtualScroller>
</template>Scrollbar Mode Configuration
When ctrlType="scrollbar", you can control the thickness of the scrollbar via scrollbarSize to adapt to different UI densities.
Available values: mini (ultra-thin), small, default, large, xlarge.
<template>
<div style="height: 60px;">
<TuiVirtualScroller ctrlType="scrollbar" scrollbarSize="mini">
<div v-for="i in 10" :key="i" class="item">Mini Scrollbar</div>
</TuiVirtualScroller>
</div>
</template>Form Component Adaptation
Similar to StepScroller, VirtualScroller is deeply adapted for TuiRadio and TuiCheckbox. When there are too many options, using this component prevents excessive occupation of page space.
It is recommended to set border="auto" or border="none" for the best visual effect.
<script setup>
import { ref } from 'vue'
const radioVal = ref(1)
const checkVal = ref([])
</script>
<template>
<div style="height: 50px;">
<TuiVirtualScroller border="auto">
<TuiRadio v-model="radioVal" appearance="button">
<TuiRadioItem v-for="i in 20" :key="i" :value="i">Opt{{ i }}</TuiRadioItem>
</TuiRadio>
</TuiVirtualScroller>
</div>
<div style="height: 50px; margin-top: 20px;">
<TuiVirtualScroller border="none">
<TuiCheckbox v-model="checkVal" appearance="button">
<TuiCheckboxItem v-for="i in 20" :key="i" :value="i">Chk{{ i }}</TuiCheckboxItem>
</TuiCheckbox>
</TuiVirtualScroller>
</div>
</template>Vertical Direction
Set direction="v" to enable vertical scrolling. Please ensure you set an explicit height for the parent container.
<template>
<div style="height: 300px; width: 200px;">
<TuiVirtualScroller direction="v" ctrlType="scrollbar">
<div v-for="i in 20" :key="i" class="v-item">Vertical {{ i }}</div>
</TuiVirtualScroller>
</div>
</template>API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| direction | Scroll direction, optional 'h', 'v' | String | 'h' |
| ctrlType | Controller type, optional 'scrollbar', 'button', 'none' | String | 'scrollbar' |
| border | Border strategy, optional 'auto', 'none', 'always' | String | 'auto' |
| buttonPosition | Button position (button mode only), optional 'both', 'start', 'end', 'float' | String | 'both' |
| buttonSize | Button size (button mode only), optional 'default', 'small', 'large' | String | 'default' |
| scrollbarSize | Scrollbar thickness (scrollbar mode only), optional 'mini', 'small', 'default', 'large', 'xlarge' | String | 'small' |
| scrollSpeed | Scrolling speed multiplier in button scroll mode | Number | 1 |
| resizeObserver | Size observation strategy, optional 'self', 'global', 'none' | String | 'self' |
Expose
The component exposes the following methods, which can be called via ref to achieve programmatic scrolling.
| Name | Description | Type |
|---|---|---|
| scrollTo | Scroll to a specific pixel position | (position: number) => void |
| scrollToTop | Scroll to the top (or far left) | () => void |
| scrollToBottom | Scroll to the bottom (or far right) | () => void |
| scrollPosition | Get the current scroll position (pixels) | number (Ref) |
| maxScroll | Get the maximum scrollable distance | number (Ref) |
Slots
| Slot Name | Description |
|---|---|
| default | Content inside the scroll container |