Having fun with useScroll in VueJS

Foto del autor

By adm_akb

November 9, 2022

By Raul Sposito, Software Developer @ Arionkoder.

There’s an amazing collection of composition utilities called VueUse 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 everyday development a lot simpler.

We will cover a few fun use cases for the 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 instantiate an element in the script with that ‘ref’. Looking like this:

<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.

<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 its 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:

<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 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.

<div>{{ scroll }}</div>

So now you 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:

<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 it does the job for this example.

Feel free to check out the whole code example on Stackblitz!

Imagine also that you would like to add some animation or 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.