How To Trigger a Scroll Event in Vue.js With the IntersectionObserver
Animate your pages when an element is visible in the viewport with pure JavaScript

In my experience as a frontend developer, one of the things that I often develop are animations on the scrolling of the pages.
My approach to this type of development has changed over the years.
At first, I used the scroll event in JavaScript, but on the performance side, I realized that it was not a great way to trigger an event every time the user scrolled the page.
Later I decided to use external libraries like ScrollMagic, wow.js, AOS etc.
I was always happy with the result (even if they were limited to animate), but nowadays the performances of a website are very important, so I asked myself, do I really need external libraries to create simple effects on the scroll? They add weight to the bundle size.
What I use today when I have to run animations or trigger events on the scroll of the pages is the Intersection Observer API.
I read an interesting article that explains the difference in performance between the scroll listener and the Intersection Observer that I recommend you to read to understand better its potential.
Today we are going to develop a component in Vue.js, which will take care to trigger an event when it is visible in the viewport.
What can you do with the Intersection Observer API?
You can observe changes in the intersection of an element with the document’s viewport.
I don’t want to go deeper into this topic because I want to focus more on the practice, but you can read more here.
Browser Support
The Intersection Observer is supported by the most used browsers, you can check the list here.
Now let’s start creating our component.
We will use some class of TailwindCSS in this example.
The IntersectionObserver component
IntersectionObserver.vue
<template>
<div :ref="sentinalName" class="w-full h-px relative" />
</template><script>
export default {
name: 'IntersectionObserver',props: {
sentinalName: {
type: String,
required: true,
},
},data(){
return {
isIntersectingElement: false,
}
},watch: {
isIntersectingElement: function(value) {
this.$emit('on-intersection-element', value)
},
},mounted() {
const sentinal = this.$refs[this.sentinalName]
const handler = (entries) => {
if (entries[0].isIntersecting) {
this.isIntersectingElement = true
}
else {
this.isIntersectingElement = false
}
}
const observer = new window.IntersectionObserver(handler)
observer.observe(sentinal)
},
}
</script>
We may have multiple Intersection Observer on our pages so we need to make them unique through a prop
.
We reference our element through a ref
(read more about ref here).
Inside the mounted
we use the Intersection Observer API we have talked about so much, here if our element is intersecting the viewport, the isIntersectingElement
value inside our data
object will be set to true otherwise to false.
Then we set up a watch
that will take care of emitting a custom event(passing the value) every time the value of the data isIntersectingElement
changes.
Now from the parent we can receive the event with its value and do whatever we like.
Let’s add our component to the point of the page where we want to trigger the event.
YourPage.vue
<intersection-observer
sentinal-name="sentinal-name"
@on-intersection-element="onIntersectionElement"
></intersection-observer>
At this point, we create a method onIntersectionElement
, where we get a true or false value that tells us if the element intersects in our viewport or not, in this method
we can do whatever we want according to our needs(start an animation, trigger an event, etc.).
YourPage.vue
onIntersectionElement(value) {
// value will be true when the component is visible on the page
otherwise false
// you can do whatever you want
},
I have prepared a demo of simple animation with the IntersectionObserver component on Codesandbox, you can have a look here
Conclusion
If you want to add page scrolling animations or trigger an event when scrolling to a specific point, I recommend you to consider this approach before importing external libraries.
The performance of your website will be better and the bundle size will smile at you.