useScroll
Reactive scroll position and state.
Demo
TopLeft
BottomLeft
TopRight
BottomRight
Scroll Me
X Position
Y Position
isScrollingfalse
Top Arrived
true Right Arrived
false Bottom Arrived
false Left Arrived
true Scrolling Up
false Scrolling Right
false Scrolling Down
false Scrolling Left
falseUsage
html
<script setup lang="ts">
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y, isScrolling, arrivedState, directions } = useScroll(el)
</script>
<template>
<div ref="el"></div>
</template>
<script setup lang="ts">
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y, isScrolling, arrivedState, directions } = useScroll(el)
</script>
<template>
<div ref="el"></div>
</template>
With offsets
js
const { x, y, isScrolling, arrivedState, directions } = useScroll(el, {
offset: { top: 30, bottom: 30, right: 30, left: 30 },
})
const { x, y, isScrolling, arrivedState, directions } = useScroll(el, {
offset: { top: 30, bottom: 30, right: 30, left: 30 },
})
Setting scroll position
Set the x
and y
values to make the element scroll to that position.
vue
<script setup lang="ts">
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y } = useScroll(el)
</script>
<template>
<div ref="el" />
<button @click="x += 10">
Scroll right 10px
</button>
<button @click="y += 10">
Scroll down 10px
</button>
</template>
<script setup lang="ts">
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y } = useScroll(el)
</script>
<template>
<div ref="el" />
<button @click="x += 10">
Scroll right 10px
</button>
<button @click="y += 10">
Scroll down 10px
</button>
</template>
Smooth scrolling
Set behavior: smooth
to enable smooth scrolling. The behavior
option defaults to auto
, which means no smooth scrolling. See the behavior
option on window.scrollTo()
for more information.
ts
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y } = useScroll(el, { behavior: 'smooth' })
// Or as a `ref`:
const smooth = ref(false)
const behavior = computed(() => smooth.value ? 'smooth' : 'auto')
const { x, y } = useScroll(el, { behavior })
import { useScroll } from '@vueuse/core'
const el = ref<HTMLElement | null>(null)
const { x, y } = useScroll(el, { behavior: 'smooth' })
// Or as a `ref`:
const smooth = ref(false)
const behavior = computed(() => smooth.value ? 'smooth' : 'auto')
const { x, y } = useScroll(el, { behavior })
Directive Usage
This function also provides a directive version via the
@vueuse/components
package. Learn more about the usage.
html
<script setup lang="ts">
import type { UseScrollReturn } from '@vueuse/core'
import { vScroll } from '@vueuse/components'
const data = ref([1, 2, 3, 4, 5, 6])
function onScroll(state: UseScrollReturn) {
console.log(state) // {x, y, isScrolling, arrivedState, directions}
}
</script>
<template>
<div v-scroll="onScroll">
<div v-for="item in data" :key="item">
{{ item }}
</div>
</div>
<!-- with options -->
<div v-scroll="[onScroll, { 'throttle' : 10 }]">
<div v-for="item in data" :key="item">
{{ item }}
</div>
</div>
</template>
<script setup lang="ts">
import type { UseScrollReturn } from '@vueuse/core'
import { vScroll } from '@vueuse/components'
const data = ref([1, 2, 3, 4, 5, 6])
function onScroll(state: UseScrollReturn) {
console.log(state) // {x, y, isScrolling, arrivedState, directions}
}
</script>
<template>
<div v-scroll="onScroll">
<div v-for="item in data" :key="item">
{{ item }}
</div>
</div>
<!-- with options -->
<div v-scroll="[onScroll, { 'throttle' : 10 }]">
<div v-for="item in data" :key="item">
{{ item }}
</div>
</div>
</template>
Type Declarations
Show Type Declarations
typescript
export interface UseScrollOptions {
/**
* Throttle time for scroll event, it’s disabled by default.
*
* @default 0
*/
throttle?: number
/**
* The check time when scrolling ends.
* This configuration will be setting to (throttle + idle) when the `throttle` is configured.
*
* @default 200
*/
idle?: number
/**
* Offset arrived states by x pixels
*
*/
offset?: {
left?: number
right?: number
top?: number
bottom?: number
}
/**
* Trigger it when scrolling.
*
*/
onScroll?: (e: Event) => void
/**
* Trigger it when scrolling ends.
*
*/
onStop?: (e: Event) => void
/**
* Listener options for scroll event.
*
* @default {capture: false, passive: true}
*/
eventListenerOptions?: boolean | AddEventListenerOptions
/**
* Optionally specify a scroll behavior of `auto` (default, not smooth scrolling) or
* `smooth` (for smooth scrolling) which takes effect when changing the `x` or `y` refs.
*
* @default 'auto'
*/
behavior?: MaybeComputedRef<ScrollBehavior>
}
/**
* Reactive scroll.
*
* @see https://vueuse.org/useScroll
* @param element
* @param options
*/
export declare function useScroll(
element: MaybeComputedRef<
HTMLElement | SVGElement | Window | Document | null | undefined
>,
options?: UseScrollOptions
): {
x: WritableComputedRef<number>
y: WritableComputedRef<number>
isScrolling: Ref<boolean>
arrivedState: {
left: boolean
right: boolean
top: boolean
bottom: boolean
}
directions: {
left: boolean
right: boolean
top: boolean
bottom: boolean
}
}
export type UseScrollReturn = ReturnType<typeof useScroll>
export interface UseScrollOptions {
/**
* Throttle time for scroll event, it’s disabled by default.
*
* @default 0
*/
throttle?: number
/**
* The check time when scrolling ends.
* This configuration will be setting to (throttle + idle) when the `throttle` is configured.
*
* @default 200
*/
idle?: number
/**
* Offset arrived states by x pixels
*
*/
offset?: {
left?: number
right?: number
top?: number
bottom?: number
}
/**
* Trigger it when scrolling.
*
*/
onScroll?: (e: Event) => void
/**
* Trigger it when scrolling ends.
*
*/
onStop?: (e: Event) => void
/**
* Listener options for scroll event.
*
* @default {capture: false, passive: true}
*/
eventListenerOptions?: boolean | AddEventListenerOptions
/**
* Optionally specify a scroll behavior of `auto` (default, not smooth scrolling) or
* `smooth` (for smooth scrolling) which takes effect when changing the `x` or `y` refs.
*
* @default 'auto'
*/
behavior?: MaybeComputedRef<ScrollBehavior>
}
/**
* Reactive scroll.
*
* @see https://vueuse.org/useScroll
* @param element
* @param options
*/
export declare function useScroll(
element: MaybeComputedRef<
HTMLElement | SVGElement | Window | Document | null | undefined
>,
options?: UseScrollOptions
): {
x: WritableComputedRef<number>
y: WritableComputedRef<number>
isScrolling: Ref<boolean>
arrivedState: {
left: boolean
right: boolean
top: boolean
bottom: boolean
}
directions: {
left: boolean
right: boolean
top: boolean
bottom: boolean
}
}
export type UseScrollReturn = ReturnType<typeof useScroll>
Source
Contributors
Anthony Fu
webfansplz
Curt Grimes
kongmoumou
丶远方
holtergram
Ayaka Rizumu
云游君
btea
Thierry Michel
Pavel Yankovski
Bobakanoosh
Joseph Fitz Hughes