It's Christmas, get a 30% OFF. Apply code XMAS at checkout.

← Back to all tutorials

How to animate objects on scroll with Tailwind CSS and the JavaScript intersection observer API

The image is a simple text-based graphic with the phrase SCROLL TO SEE EFFECTS centered on a light background. This suggests that the image may be part of an interactive web page or presentation where scrolling down will trigger certain animations or visual changes.
Published and written on Jun 03 2024 by Michael Andreuzza

Good Monday everyone! Finally my favourite day of the week, and I’m excited to share with you a new tutorial on how to animate objects with Tailwind CSS and JavaScript intersection observer API. This tutorial will show you how to create a simple animation when an element enters the viewport, using the Intersection Observer API with JavaScript and Tailwind CSS.

What is the Intersection Observer API?

The Intersection Observer API is a JavaScript API that allows you to observe the visibility of elements on a web page. It provides a way to detect when an element enters or exits the viewport, and triggers a callback function when the element is visible.

Traditionally, identifying whether an element is visible or comparing the visibility of two elements has been difficult, often leading to unreliable methods and sluggish browser performance. With the evolution of the web, the demand for such information has grown. Intersection data is essential for several reasons, such as:

  • Lazy-loading images or other content as the user scrolls.
  • Creating “infinite scrolling” websites, where content continuously loads as the user scrolls, eliminating the need for pagination.
  • Tracking ad visibility to calculate advertising revenue.
  • Deciding whether to execute tasks or animations based on whether the user will see the outcome.

and other use cases.

The markup

  • The Id id="rotateYImage" is used to reference the image element in the JavaScript code. On this case, the image is rotated around the Y-axis.
  • The Id id="rotateXImage" is used to reference the image element in the JavaScript code. On this case, the image is rotated around the X-axis.
<section>
  <div>
    <img
      id="rotateYImage"
      src="https://i.pinimg.com/564x/78/d1/c0/78d1c06554aead1dc1d1490f08d39ffd.jpg" />
  </div>
</section>
<section>
  <div>
    <img
      id="rotateXImage"
      src="https://i.pinimg.com/564x/78/d1/c0/78d1c06554aead1dc1d1490f08d39ffd.jpg" />
  </div>
</section>

The script

The event listeners

  • const rotateYImage = document.getElementById("rotateYImage"): This line of code selects the element with the id rotateYImage and assigns it to the variable rotateYImage.
  • const rotateXImage = document.getElementById("rotateXImage"): This line of code selects the element with the id rotateXImage and assigns it to the variable rotateXImage.
const rotateYImage = document.getElementById("rotateYImage");
const rotateXImage = document.getElementById("rotateXImage");

The observer

  • const createObserver = (element, rotateProperty, targetDegree, step) => {: This line of code defines a function called createObserver that takes four parameters: element, rotateProperty, targetDegree, and step.
  • let degree = 0;: This line of code initializes a variable called degree to 0. It will be used to keep track of the current rotation angle of the element.
  • const observer = new IntersectionObserver((entries) => {: This line of code creates a new instance of the IntersectionObserver class and assigns it to the variable observer.
  • entries.forEach((entry) => {: This line of code iterates over each entry in the entries array and calls a function for each entry.
  • if (entry.isIntersecting) {: This line of code checks if the entry is intersecting with the viewport.
  • const interval = setInterval(() => {: This line of code creates a new interval and assigns it to the variable interval.
  • if (degree < targetDegree) {: This line of code checks if the current rotation angle is less than the target rotation angle.
  • degree += step;: This line of code increments the current rotation angle by the step value.
  • element.style.transform = perspective(1000px) ${rotateProperty}(${degree}deg): This line of code sets the transform property of the element to perspective(1000px) rotateY(degree)deg`.
  • } else {: This line of code checks if the current rotation angle is greater than or equal to the target rotation angle.
  • clearInterval(interval);: This line of code clears the interval and stops the rotation animation.
  • }, 50);: This line of code sets the interval to run every 50 milliseconds.
const createObserver = (element, rotateProperty, targetDegree, step) => {
  let degree = 0;
  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        const interval = setInterval(() => {
          if (degree < targetDegree) {
            degree += step;
            element.style.transform = `perspective(1000px) ${rotateProperty}(${degree}deg)`;
          } else {
            clearInterval(interval);
          }
        }, 50);
      }
    });
  });
  observer.observe(element);
};

Creating the observer

  • createObserver(rotateYImage, "rotateY", 360, 5);: This line of code calls the createObserver function with the rotateYImage element, the rotateY property, the target rotation angle of 360 degrees, and a step value of 5.
  • createObserver(rotateXImage, "rotateX", 30, 1);: This line of code calls the createObserver function with the rotateXImage element, the rotateX property, the target rotation angle of 30 degrees, and a step value of 1.
createObserver(rotateYImage, "rotateY", 360, 5);
createObserver(rotateXImage, "rotateX", 30, 1);

The full script

document.addEventListener("DOMContentLoaded", function () {
  const rotateYImage = document.getElementById("rotateYImage");
  const rotateXImage = document.getElementById("rotateXImage");

  const createObserver = (element, rotateProperty, targetDegree, step) => {
    let degree = 0;
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const interval = setInterval(() => {
            if (degree < targetDegree) {
              degree += step;
              element.style.transform = `perspective(1000px) ${rotateProperty}(${degree}deg)`;
            } else {
              clearInterval(interval);
            }
          }, 50);
        }
      });
    });
    observer.observe(element);
  };

  createObserver(rotateYImage, "rotateY", 360, 5);
  createObserver(rotateXImage, "rotateX", 30, 1);
});

Conclusion

In this tutorial, we learned how to use the Intersection Observer API to animate objects in a web page. We created a simple animation when an element enters the viewport, using the Intersection Observer API with JavaScript and Tailwind CSS.

Hope you enjoyed this tutorial and have a nice day!

/Michael Andreuzza

Did you like this tutorial? Please share it with your friends!

Unlock all themes for $199 for forever! Includes lifetime updates, new themes, unlimited projects, and support. No subscription needed.

— No subscription required!