Having fun with useScroll in VueJS
Tags: vue, vueuse
Published: 2022-10-28 14:10:40

There's an amazing collection of composition utilities called [VueUse](https://vueuse.org/) and if you don't know about it make sure to check it out because there's a ton of cool stuff there that will make your every day developing a lot simpler.

We will be covering a few fun use cases for the [useScroll](https://vueuse.org/core/useScroll/) utility and how that can, with very few lines of code, achieve some cool reactive effects in our layouts.

To get started, just run `npm i @vueuse/core` on the terminal and make sure you import `import { useScroll } from '@vueuse/core'` into the component you're going to be listening for scroll events.

In this example I'm also using 'ref' so you would need to import `import { ref } from 'vue';` as well as to instantiate an element in the script with that 'ref'.  Looking like this:

```javascript
<script setup>
import { ref } from 'vue';
import { useScroll } from '@vueuse/core';

const el = ref(null);
const scroll = useScroll(el);
</script>
```

Cool! We have assigned a ref to an element and we will be listening for all the scrolls on it. Now we need to reference that in the template so our users can actually scroll over it.

```javascript
<template>
  <div class="scroll-box" ref="el">
    “It is a period of civil war. Rebel spaceships, striking from a hidden base,
    have won their first victory against the evil Galactic Empire. During the
    battle, Rebel spies managed to steal secret plans to the Empire’s ultimate
    weapon, the DEATH STAR, and space station with enough power to destroy an
    entire planet. Pursued by the Empire’s sinister agents, Princess Leia races
    home aboard her starship, custodian of the stolen plans that can save her
    people and restore freedom to the galaxy….”
  </div>
  <div>{{ scroll }}</div>
</template>
```

As you can see, we are using that same ref to link it together and inside that element, we have placed a long text (Star Wars opening Crawl) that will overflow the container and enable it's ability to be scrollable. For this, we will also need to use CSS to set a max height, or height to that container and to also enable for `overflow: scroll;`. It will look like the following:

```javascript
<style scoped>
.scroll-box {
  color: white;
  background-color: black;
  height: 150px;
  width: 100%;
  overflow: scroll;
  position: relative;
}
</style>
```

With that, we have enough to get started on the magic!

Here's the fun part, useScroll returns for us an object that we can play with and do all our creativity allows us to. The object will look like the following:

```
{ "x": 0, "y": 0, "isScrolling": false, "arrivedState": { "left": true, "right": true, "top": true, "bottom": false }, "directions": { "left": false, "right": false, "top": false, "bottom": false } }
```

And you can actually go ahead and print it on the screen, to see what I'm talking about.

```javascript
<div>{{ scroll }}</div>
```

So now you kind of get the idea of where this is going.

Let's say we want to perform a certain action whenever our user has reached the end of the scroll, something like showing or hiding something. We can use the "arrivedState" property of our use scroll and listen for it when it reaches "bottom" (when bottom = true).

So we can add conditional render to the element we want to add and link that to our useScroll object, as follows:

```javascript
<p v-show="scroll.arrivedState.bottom">you have reached the bottom!</p>
```

I also added a simple button to be able to click on it and reset the whole flow without having to reload the page. It's not the fanciest but does the job for this example.

Feel free to check out the whole code example on [Stackblitz](https://stackblitz.com/edit/vitejs-vite-xkr9a8)!

Imagine also that you would like to add some animation or to display something while the user is performing the scroll, to give it some sense of dynamism. You can also listen for the "isScrolling" attribute of the useScroll object and link that to trigger the animation! Or you can listen for a given point in the "y" axis and fire events or display different content based on it.

The possibilities are only limited by what we can imagine :) since the technical part is now super simple!

Hope you enjoyed this, since it's the first of a series regarding this wonderful VueUse library.