Skip to content

VirtualScrollbar

Темизируемый кастомный оверлей скроллбара. Отделён от useVirtualScroll — он работает с элементом прокрутки, предоставляемым любым из компонентов выше (через getScrollElement()), либо с любым прокручиваемым элементом, переданным напрямую. Рендерит трек + перетаскиваемый ползунок, размер и позиция которого вычисляются из scrollHeight/clientHeight/scrollTop, перетаскивание — через pointer-события.

Ползунок — полноценный виджет role="scrollbar": aria-orientation/aria-valuemin/aria-valuemax/aria-valuenow отражают текущую позицию прокрутки, и им можно управлять с клавиатуры — стрелки сдвигают позицию, Home/End прыгают к началу/концу, PageUp/PageDown — на размер вьюпорта.

Пропы

target

() => HTMLElement | null

Возвращает элемент прокрутки для синхронизации.

orientation

'vertical' | 'horizontal' · по умолчанию: 'vertical'

Ось прокрутки для отслеживания.

minThumbSize

number · по умолчанию: 24

Минимальный размер ползунка в px, чтобы огромный список не сжимал его до неухватываемой полоски.

Публичный API

refresh()

Принудительно переподключиться и пересчитать состояние против текущего target() — полезно после ручной замены DOM, которую собственные ResizeObserver/слушатели прокрутки компонента иначе не заметят.

ts
scrollbarRef.value?.refresh()

CSS custom properties

--vvsk-scrollbar-size

По умолчанию: 10px

Толщина трека/ползунка.

--vvsk-scrollbar-track

По умолчанию: transparent

Фон трека.

--vvsk-scrollbar-thumb

По умолчанию: rgb(255 255 255 / 25%)

Фон ползунка.

--vvsk-scrollbar-thumb-hover

По умолчанию: rgb(255 255 255 / 40%)

Фон ползунка при наведении/перетаскивании.

Пример

vue
<script setup lang="ts">
import { ref } from 'vue'
import { VirtualList, VirtualScrollbar } from 'vue-virtual-scroller-kit'
import type { VirtualListExpose } from 'vue-virtual-scroller-kit'

const listRef = ref<VirtualListExpose | null>(null)
const items = Array.from({ length: 10_000 }, (_, i) => ({ id: i, text: `Row ${i + 1}` }))
</script>

<template>
  <div style="position: relative; display: flex; height: 500px">
    <VirtualList
      ref="listRef"
      :items="items"
      :estimated-item-size="48"
      class="vvsk-scrollbar-hidden"
      style="flex: 1"
    >
      <template #default="{ item }">
        <div style="padding: 12px 16px; border-bottom: 1px solid #eee">{{ item.text }}</div>
      </template>
    </VirtualList>

    <VirtualScrollbar :target="() => listRef?.getScrollElement() ?? null" />
  </div>
</template>

Скрыть нативный скроллбар на связанном контейнере при использовании VirtualScrollbar (опционально — они могут сосуществовать, если нужны оба):

css
.vvsk-scrollbar-hidden {
  scrollbar-width: none; /* Firefox */
}
.vvsk-scrollbar-hidden::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Edge */
}