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

Luca Spezzano
Feb 16 · 3 min read
Image for post
Image for post
Photo by Priscilla Du Preez on Unsplash

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.

NotOnlyCSS

This publication includes original articles and tips about…

Sign up for NotOnlyCSS

By NotOnlyCSS

Articles and tips for frontend developers Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Luca Spezzano

Written by

Frontend developer focused on CSS architecture of scalable and maintainable large scale projects and the development of amazing user interfaces.

NotOnlyCSS

This publication includes original articles and tips about frontend technologies.

Luca Spezzano

Written by

Frontend developer focused on CSS architecture of scalable and maintainable large scale projects and the development of amazing user interfaces.

NotOnlyCSS

This publication includes original articles and tips about frontend technologies.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store