Skip to content
Advertisement

Use IntersectionObserver To Trigger Event AFTER Element Completely Passes Threshold

I have a few IntersectionObserver‘s set up. observer toggles new boxes to be made as the user scrolls down the page. lastBoxObserver loads new boxes as this continuous scrolling happens.

What I would like to do is change the color of a box once it leaves the threshold set in the first observer (observer – whose threshold is set to 1). So, once box 12 enters the viewport, it passes through the observer, and once it has completely passed outside of the threshold for this observer and box 13 enters the observer, box 12’s background changes from green to orange, perhaps.

Is there a way to make this happen? Maybe by adding an additional observer, or adding code to observer? Any help is greatly appreciated.

Codepen: https://codepen.io/jon424/pen/NWwReEJ

JavaScript

 const boxes = document.querySelectorAll(".box");
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          entry.target.classList.toggle("show", entry.isIntersecting);
          if (entry.isIntersecting) observer.unobserve(entry.target);
        });
      },
      {
        threshold: 1,
      }
    );

    const lastBoxObserver = new IntersectionObserver((entries) => {
      const lastBox = entries[0];
      if (!lastBox.isIntersecting) return;
      loadNewBoxes();
      lastBoxObserver.unobserve(lastBox.target);
      lastBoxObserver.observe(document.querySelector(".box:last-child"));
    }, {});

    lastBoxObserver.observe(document.querySelector(".box:last-child"));

    boxes.forEach((box) => {
      observer.observe(box);
    });

    const boxContainer = document.querySelector(".container");

    function loadNewBoxes() {
      for (let i = 0; i < 1000; i++) {
        const box = document.createElement("div");
        box.textContent = `${i + 1}`;
        box.classList.add("box");
        observer.observe(box);
        boxContainer.appendChild(box);
      }
    }

HTML

   <div class="container">
      <div class="box">0</div>
    </div>

CSS

 .container {
      display: flex;
      flex-direction: column;
      gap: 1rem;
      align-items: flex-start;
    }

    .box {
      background: green;
      color: white;
      font-size: 4rem;
      text-align: center;
      margin: auto;
      height: 100px;
      width: 100px;
      border: 1px solid black;
      border-radius: 0.25rem;
      padding: 0.5rem;
      transform: translateX(100px);
      opacity: 0;
      transition: 150ms;
    }

    .box.show {
      transform: translateX(0);
      opacity: 1;
    }

    .box.show.more {
      background-color: orange;
    }

Advertisement

Answer

You just need to add color change logic in your first observer.

I tested with the following changes to your code,

In css, change .box.show.more to –

.box.more {
      background-color: orange;
}

In javascript –

const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          entry.target.classList.toggle("show", entry.isIntersecting);
          if (entry.isIntersecting) {
            observer.unobserve(entry.target);
            
            if(entry.target.textContent === '13')
                      entry.target.previousSibling.classList.toggle('more');
          }
        });
      },
      {
        threshold: 1,
      }
    );

As you can see, the only change is that I added this part –

if(entry.target.textContent === '13')
    entry.target.previousSibling.classList.toggle('more');

I also changed the number of new div to add from 1000 to 20 for easy test.

If you want to change box 12 color as soon as box 13 enters viewport, you can simply change “threshold” from 1 to 0.

Advertisement