Skip to content

Scrollbar ​

Custom scrollbar that replaces the native browser scrollbar with a styled overlay.

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

vue
<template>
  <VxScrollbar height="200px">
    <p v-for="i in 20" :key="i">Item {{ i }}</p>
  </VxScrollbar>
</template>

Horizontal ​

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vue
<template>
  <VxScrollbar>
    <div style="display: flex; gap: 12px; width: max-content">
      <div v-for="i in 20" :key="i" class="card">{{ i }}</div>
    </div>
  </VxScrollbar>
</template>

Max Height ​

Content shorter than max-height won't show a scrollbar.

Scrollable item 1

Scrollable item 2

Scrollable item 3

Scrollable item 4

Scrollable item 5

Scrollable item 6

Scrollable item 7

Scrollable item 8

Scrollable item 9

Scrollable item 10

Scrollable item 11

Scrollable item 12

Scrollable item 13

Scrollable item 14

Scrollable item 15

Scrollable item 16

Scrollable item 17

Scrollable item 18

Scrollable item 19

Scrollable item 20

Scrollable item 21

Scrollable item 22

Scrollable item 23

Scrollable item 24

Scrollable item 25

Scrollable item 26

Scrollable item 27

Scrollable item 28

Scrollable item 29

Scrollable item 30

vue
<template>
  <VxScrollbar max-height="200px">
    <p v-for="i in 30" :key="i">Scrollable item {{ i }}</p>
  </VxScrollbar>
</template>

Always Visible ​

Show the scrollbar even when not hovering.

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

vue
<template>
  <VxScrollbar height="200px" always>
    <p v-for="i in 20" :key="i">Item {{ i }}</p>
  </VxScrollbar>
</template>

Sizes ​

Control the thumb thickness with the size prop.

sm

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

default

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

lg

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

vue
<template>
  <VxScrollbar height="150px" size="sm" always>...</VxScrollbar>
  <VxScrollbar height="150px" always>...</VxScrollbar>
  <VxScrollbar height="150px" size="lg" always>...</VxScrollbar>
</template>

Native ​

Use the browser's native scrollbar instead.

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

vue
<template>
  <VxScrollbar height="200px" native>
    <p v-for="i in 20" :key="i">Item {{ i }}</p>
  </VxScrollbar>
</template>

Infinite Scroll ​

Automatically loads more content when scrolling near the bottom. The infinite event fires when the scroll position reaches the distance threshold from the bottom.

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

vue
<script setup>
import { ref } from 'vue'

const items = ref(Array.from({ length: 20 }, (_, i) => i + 1))
const loading = ref(false)

function loadMore() {
  if (loading.value) return
  loading.value = true
  setTimeout(() => {
    const start = items.value.length
    for (let i = 1; i <= 10; i++) {
      items.value.push(start + i)
    }
    loading.value = false
  }, 800)
}
</script>

<template>
  <VxScrollbar height="200px" infinite :distance="20" @infinite="loadMore">
    <p v-for="item in items" :key="item">Item {{ item }}</p>
    <div v-if="loading">Loading...</div>
  </VxScrollbar>
</template>

Scroll End ​

The scrollend event fires when the user stops scrolling.

Scroll to see event

Item 1

Item 2

Item 3

Item 4

Item 5

Item 6

Item 7

Item 8

Item 9

Item 10

Item 11

Item 12

Item 13

Item 14

Item 15

Item 16

Item 17

Item 18

Item 19

Item 20

Item 21

Item 22

Item 23

Item 24

Item 25

Item 26

Item 27

Item 28

Item 29

Item 30

vue
<script setup>
function onScrollEnd(e) {
  console.log('Scroll ended!', e)
}
</script>

<template>
  <VxScrollbar height="200px" @scrollend="onScrollEnd">
    <p v-for="i in 30" :key="i">Item {{ i }}</p>
  </VxScrollbar>
</template>

Props ​

PropTypeDefaultDescription
heightstring''Fixed height
maxHeightstring''Maximum height
nativebooleanfalseUse native scrollbar
alwaysbooleanfalseAlways show scrollbar
size'sm' | 'default' | 'lg''default'Scrollbar thumb thickness
infinitebooleanfalseEnable infinite scroll
distancenumber0Pixel threshold from bottom to trigger infinite
noresizebooleanfalseDisable resize observer
tagstring'div'Wrapper element tag

Exposed Methods ​

MethodTypeDescription
scrollTo(options: ScrollToOptions) => voidScroll to position
setScrollTop(top: number) => voidSet vertical scroll
setScrollLeft(left: number) => voidSet horizontal scroll
update() => voidRecalculate scrollbar

Events ​

EventTypeDescription
scroll(e: Event) => voidFires on scroll
scrollend(e: Event) => voidFires when scrolling stops
infinite() => voidFires when scroll reaches bottom threshold