Skip to content

Virtual Scroller

Star
👑Pioneer

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.

vue
<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.
vue
<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.

vue
<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.

vue
<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.

vue
<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.

vue
<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

PropertyDescriptionTypeDefault
directionScroll direction, optional 'h', 'v'String'h'
ctrlTypeController type, optional 'scrollbar', 'button', 'none'String'scrollbar'
borderBorder strategy, optional 'auto', 'none', 'always'String'auto'
buttonPositionButton position (button mode only), optional 'both', 'start', 'end', 'float'String'both'
buttonSizeButton size (button mode only), optional 'default', 'small', 'large'String'default'
scrollbarSizeScrollbar thickness (scrollbar mode only), optional 'mini', 'small', 'default', 'large', 'xlarge'String'small'
scrollSpeedScrolling speed multiplier in button scroll modeNumber1
resizeObserverSize 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.

NameDescriptionType
scrollToScroll to a specific pixel position(position: number) => void
scrollToTopScroll to the top (or far left)() => void
scrollToBottomScroll to the bottom (or far right)() => void
scrollPositionGet the current scroll position (pixels)number (Ref)
maxScrollGet the maximum scrollable distancenumber (Ref)

Slots

Slot NameDescription
defaultContent inside the scroll container

Released under the MIT License.