Scroll Animations with Intersection Observer

When creating even the most basic scrolling animations, there are many steps involved just to add or remove a class name with JavaScript. With modern ES6 syntax, it’s time to simplify how much effort is needed by taking advantage of the Intersection Observer API. In this article, I’ll show you how to create a basic Intersection Observer that will add or remove a CSS blur when an object has entered or left the viewport.

What is Intersection Observer?

Intersection Observer is a really awesome JavaScript API that simplifies scroll-based events in JavaScript. Rather than constantly checking the distance from the top, Intersection Observer watches when an element enters or exits the viewport. It’s really that simple, and you can create features such as scroll animations, lazy loading images, inserting new elements into the DOM, and triggering notifications.

The IntersectionObserver interface of the Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport. The ancestor element or viewport is referred to as the root.

 –MDN Web Docs

Let’s Build an Observer

When I first started experimenting with Intersection Observer, I quickly learned that it’s easier to experiment and learn from trial and error and then refer back to the documentation. The pen below is the full example of the demo I put together for this article, which you can use to follow along with.

Intersection Observer Options

By default, Intersection Observer has three properties that are read-only and cannot be modified once set. These properties are root, rootMargin, and thresholds. Each property can modify how the observer behaves while it’s running. For a full definition of each property checkout the MDN documention.


The first property, root,  is the container that that will act as our viewport area. When the element that is being observed is inside of this container it will have the property of isIntersecting: true. If the element falls outside of the viewport then isIntersecting is set to false. Setting a value of null will allow you to set your root as the document viewport instead of a specific element.

Root Margin

The rootMargin property adds margin around the root very similar to CSS. This value is optional and defaults to “0px 0px 0px 0px.”  For example, if the root is set to the document viewport, and you had a rootMargin of 20px, then the observed element would be intersected 20px before the element passes outside of the root container. This value can also use percentages in place of pixels.


The thresholds property defines how far an element needs to intersect the root element. Using 0.7 as a threshold means that 70% of the observed element needs to be inside the root element. It’s important to know that using threshold will allow the use of only one value. Meanwhile, thresholds allows the use of an array of numerical values, which would be helpful if I were running multiple Intersection Observer instances and wanted them to behave differently.

Creating a New Observer


 ┣ 📜blur.js
 ┣ 📜dino-reichmuth-A5rCN8626Ck-unsplash.jpg (replace this with your own image).
 ┣ 📜index.html
 ┗ 📜style.css

HTML document – index.html

In index.html, I created an <img> element that will be targeted by the Intersection Observer. Next, I added a <script> tag that points to the blur.js file located in the same directory. The script tag is imported.

Adding Styles – styles.css

In style.css, I set the minimum height to be 200% of the viewport so the visible area is scrollable. Next, I added some styles to center the image in the content area. For this code example, I set the max-height of 100% of the viewport so that the scroll effect can be viewed in a very small viewport, such as a Code Pen editor.

Setting up Intersection Observer – blur.js

This file will check for an image and add or remove an inline style for a CSS blur filter. Now that the blur.js file is linked in the HTML, it’s time to create the Intersection Observer.

1. Defining Options

The first variable, heroImage, is checking for an image element in the HTML. The second variable, options, is an object with the root, rootMargin, and threshold properties that will be used in our Intersection Observer instance. By setting root: null, the observer will default to the edge of the browser viewport. The rootMargin is defined as 0px, so the observer still defaults to the edge. Lastly, I set the threshold of 0.7, which is easier to think of as 70%. When the image is less than 70% visible, that’s when our observer will activate.

2. Callback Function

The callback function is executed while an element is being observed. In this example, I’m creating the variable callback and assigning a function to it. The callback function takes in a list of IntersectionObserverEntry objects and the observer that will be created in Step 3, as seen below.

Next, I’m logging the entry objects so the interface can be viewed in the console, and then I’m rendering some inline CSS on the image element. Depending on the true or false condition of isIntersecting, a CSS blur filter will be added or removed. During the initial load, isIntersecting is true so the blur is set to 0. When scrolling beyond, the threshold value changes to false, which will apply a blur with a value of 10px.

Note: Since I’m only observing a single element for this demo, I selected the first entry in the array with entries[0]. If I were targeting multiple elements on a page, I would loop through all of the available elements instead.

3. Intersection Observer Constructor

  1. Now that the initial variables are created and the callback function is in place, I’m going to set up a new instance of Intersection Observer by using the new constructor with IntersectionObserver() and assigning that to the variable observer.
  2. Then, I’m passing in the callback function and options variable into the parameters.
  3. Lastly, it’s time to run the observer on the image element, using the observe() method on the observer variable I passed in the heroImage to observe the image element.

In this example, I want the observer to start observing when heroImage has been located and continuously check if the image is intersecting while the user is scrolling. In other scenarios, I may want to end the observer after a short time. This can be done using unobserve() method. It’s typically a good idea to only run the observer for as long as you need it.

What I learned

Intersection Observer is a really fun JavaScript feature that can make scroll-based events feel snappy with a small amount of code. I would highly recommend using this feature in cases where you need to insert, modify, or trigger an event during a scroll. It is well supported in modern browsers and has a low-performance impact. I’m looking forward to using it on more projects in the near future!

Want scrolling animations on your website?

Our team can add a solution just like this one to your media or enterprise-level website. Contact us now and let’s chat about it.


Have a comment?

Your email address will not be published. Required fields are marked *

accessibilityadminaggregationanchorarrow-rightattach-iconbackupsblogbookmarksbuddypresscachingcalendarcaret-downcartunifiedcouponcrediblecredit-cardcustommigrationdesigndevecomfriendsgallerygoodgroupsgrowthhostingideasinternationalizationiphoneloyaltymailmaphealthmessagingArtboard 1migrationsmultiple-sourcesmultisitenewsnotificationsperformancephonepluginprofilesresearcharrowscalablescrapingsecuresecureseosharearrowarrowsourcestreamsupporttwitchunifiedupdatesvaultwebsitewordpress