---
title: Scroll Observer
related:
  - title: Resize Observer
    path: resize-observer.md
---
QScrollObserver is a Quasar component that emits a `scroll` event whenever the user scrolls the page or overflowed container with `.scroll` CSS class applied to it.

## QScrollObserver API

### Props

- `debounce` (string | number, optional)
  Debounce amount (in milliseconds)
  Examples: `0`, `'530'`
- `axis` (string, optional), default `'vertical'`
  Axis on which to detect changes
  Accepts: `'both'`, `'vertical'`, `'horizontal'`
- `scroll-target` (Element | string | ComponentInstance, optional)
  CSS selector, DOM element or Vue component reference (standing for its root element) to be used as a custom scroll container instead of the auto detected one
  Examples:
    - `.scroll-target-class`
    - `#scroll-target-id`
    - `$refs.scrollTarget`
    - `$refs.scrollAreaComponent`
    - `document.body`

### Methods

- `trigger(immediately?: boolean): void`
  Emit a 'scroll' event
  Params:
    - `immediately` (boolean, optional)
      Skip over the debounce amount
- `getPosition(): void`
  Get current scroll details under the form of an Object: { position, direction, directionChanged, inflectionPoint }

### Events

- `@scroll`
  Emitted when scroll position changes
  Params:
    - `details` (object, optional)
      Scroll details
      Object shape:
        - `position` (object, required)
          Scroll offset (from top and left)
          Object shape:
            - `top` (number, required)
              Scroll offset from top (vertical)
            - `left` (number, required)
              Scroll offset from left (horizontal)
        - `direction` (string, required)
          Direction of scroll
          Accepts: `'up'`, `'down'`, `'left'`, `'right'`
        - `directionChanged` (boolean, required)
          Has scroll direction changed since event was last emitted?
        - `delta` (object, required)
          Delta of distance (in pixels) since event was last emitted
          Object shape:
            - `top` (number, required)
              Vertical delta distance since event was last emitted
            - `left` (number, required)
              Horizontal delta distance since event was last emitted
        - `inflectionPoint` (object, required)
          Last scroll offset where scroll direction has changed
          Object shape:
            - `top` (number, required)
              Scroll offset from top (vertical)
            - `left` (number, required)
              Scroll offset from left (horizontal)

## Usage

Scroll this page to see the example below in action.

Example "Basic":

```vue
<template>
  <pre class="q-ma-none container">{{ scrollInfo }}</pre>
  <q-scroll-observer @scroll="onScroll" />
</template>

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

const scrollInfo = ref({})

function onScroll(info) {
  scrollInfo.value = info
}
</script>

<style lang="sass" scoped>
.container
  font-size: 10px
</style>
```

## Determining Scrolling Container

All components or directives in Quasar have a simple algorithm to determine the container that supports the scroll:

- if a `scroll-target` property is available on the component then it tries to use it as scroll container
- then it searches for a parent DOM element which has the `scroll`, `scroll-y` or `overflow-auto` Quasar CSS helper classes attached to it,
- if none is found, then it considers that the scrolling takes place on the document itself.

Components like [QScrollArea](scroll-area.md), for example, respect this design and have the `scroll` class embedded into it, so that QScrollObservable (or any other scrolling component or directive) can successfully detect it and attach the necessary event handlers to it.

Please note that simply attaching `scroll` CSS class to a DOM element or on a Vue component will have no effect if the respective element is not overflowed (example, with: CSS `overflow: hidden` and a height smaller than its inner content height).

Example of good container:

```html
<!--
  Quasar CSS helper 'overflow-hidden' is
  equivalent to style="overflow: hidden"
-->
<div class="scroll overflow-hidden" style="height: 100px">
  ...content expanding over the 100px height from container...
  <q-scroll-observer @scroll="scrollHandler" />

  <!-- example with `v-scroll` directive -->
  <div v-scroll="scrollHandler">...</div>
</div>
```

One more example with QScrollArea:

```html
<q-scroll-area style="width: 400px; height: 500px;" class="bg-yellow">
  ...content expanding over the 500px height from container...
  <q-scroll-observer @scroll="scrollHandler" />
</q-scroll-area>
```

## Horizontal

For capturing horizontal scrolling, use the `axis="horizontal"` prop :

```html
<q-scroll-observer axis="horizontal" @scroll="scrollHandler" />
```

## Layout Scrolling

When scrolling on a Layout with a Page, rather than injecting a QScrollObservable (and by so doing registering additional scroll events) you can take advantage of [QLayout](../layout/layout.md)´s `@scroll` event directly on your component defining the Layout.

```html
<q-layout @scroll="scrollHandler">...</q-layout>
```

## Accessibility *(v2.25+)*

QScrollObserver is renderless — it emits no DOM element at all, so it has no accessibility surface.
