Search code examples
javascripthtmlcssanimationcss-animations

how to animate css element only when it appears on a window?


i know that there is parallax but i want something else like in this website joinhandshake.com

for example i have this code
html

<div class="black-div"></div>
   <div class="animated-div">
       <h1>Lorem ipsum dolor sit amet consectetur adipisicing elit. Odit temporibus fuga sit quam fugit! Dignissimos quis qui, praesentium id nihil, aspernatur nostrum, dolores dolor molestiae error molestias ipsum ipsam at.</h1>
   </div>

css


.black-div {
    background-color: black;
    height: 130vh;
}
 @keyframes rotate-scale-up {
    0% {
      transform: scale(1) rotateZ(0);
    }
    50% {
      transform: scale(2) rotateZ(180deg);
    }
    100% {
      transform: scale(1) rotateZ(360deg);
    }
  }
  .animated-div {
    animation: rotate-scale-up 0.65s linear both;
}

the problem is that when i load the page, the text gets animated, so how can i prevent that?


Solution

  • To check if an element is in view, use the Intersection Observer API. This API is built for this exact purpose and requires little to no calculations, only a check with the isIntersecting value, to see if an element has entered the view.

    The IntersectionObserverIn uses a callback function to do something whenever an element has entered or left the view. In this function you can specify what should happen when that does.

    I've made a snippet with an example on how it works and how you can implement it.

    /**
     * What to do when an item enters the screen
     * If it is in the screen, isIntersecting will be true.
     * Add a class when it is.
     */
    const intersectionCallback = (entries) => {
      for (const entry of entries) { // Loop over all elements that either enter or exit the view.
        if (entry.isIntersecting) { // This is true when the element is in view.
          entry.target.classList.add('show'); // Add a class.
        }
      }
    }
    
    /**
     * Create a observer and use the instersectionCallback as 
     * the instructions for what to do when an element enters
     * or leaves the view
     */
    const observer = new IntersectionObserver(intersectionCallback);
    
    /**
     * Get all .item elements and loop over them.
     * Observe each individual item.
     */
    const items = document.querySelectorAll('.item');
    for (const item of items) {
      observer.observe(item);
    }
    .item {
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
      height: 200px;
      width: 100%;
      margin-bottom: 20px;
      opacity: 0;
      transition: opacity 1s ease-out;
    }
    
    .item:nth-of-type(odd) {
      background-color: #333;
    }
    
    .item:nth-of-type(even) {
      background-color: #111;
    }
    
    .item.show {
      opacity: 1;
    }
    <div class="item">Hello</div>
    <div class="item">Hello</div>
    <div class="item">Hello</div>
    <div class="item">Hello</div>
    <div class="item">Hello</div>
    <div class="item">Hello</div>
    <div class="item">Hello</div>