skip to Main Content

I have a section that the animation currently only applies on page load but I would like the animation to be applied when the section appears on the screen each time I tried using the observer method for the specific class and an in ViewPort function but it doesn’t seem to be working as the animation isn’t applying when that section occurs in the page

  // Function to check if html element is in the viewport
  function isInViewport(element) {
    const rect = element.getBoundingClientRect();
    return (
      rect.top >= 0 &&
      rect.left >= 0 &&
      rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
      rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
  }
  const startAnimation = (entries, observer) => {
    entries.forEach(entry => {
      entry.target.classList.toggle("slideIn", entry.isIntersecting);
    });
  };

  const observer = new IntersectionObserver(startAnimation);
  const options = { root: null, rootMargin: '0px', threshold: 1 };

  const elements = document.querySelectorAll('.next-gen-agency');
  elements.forEach(el => {
    console.log("el = ", el);
    observer.observe(el, options);
  });
@keyframes slideIn {
  0% {
    opacity: 0;
    transform: translateY(50px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

    .next-gen-agency {
      animation: slideIn 1.5s ease-in-out forwards;
      opacity: 0;
      background-color: #E4D8D3;
      margin-top: 8rem;
    }
    
    .agency-stats {
      background-image: linear-gradient(to right,
        #00e0ff,
        #3eb6d4);
      -webkit-background-clip: text;
      background-clip: text; color: transparent;
    }
<section class="next-gen-agency" >
  <div class="container" style="display: flex; justify-content: center; align-items: center;">
    <div style="max-width: 70rem;" >
      <div style="display: flex; flex-direction: column; gap: 2rem; margin-top: 2rem;">
        <h1
          style="font-size: 4rem; font-weight: bold; background-image: linear-gradient(to right, #00e0ff, #ff007a); -webkit-background-clip: text; background-clip: text; color: transparent;">
          The Next Generation Agency.
        </h1>
        <!-- <p style="max-width: 40rem; font-size: 1.25rem; color: #c21f71">
          Our team of experts at Strive Now Management use a specialized approach to cater to your unique needs. We
          prioritize your success by understanding your goals and tailoring our strategies to help you thrive on the
          platform.
        </p> -->
        <div class="stats-div" style="display: flex; justify-content: center; align-items: center; gap: 3rem;">
          <div style="display: flex; flex-direction: column; align-items: center;">
            <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">60+</h2>
            <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">ACCOUNTS MANAGED</p>
          </div>
          <div class="stats-div" style="display: flex; flex-direction: column; align-items: center;">
            <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">25+</h2>
            <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">BRAND COLLABORATIONS</p>
          </div>
          <div class="stats-div" style="display: flex; flex-direction: column; align-items: center;">
            <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">£100k+</h2>
            <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">TOTAL EARNINGS</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

2

Answers


  1. As a quick fix if you want the animation to appear on load and on the screen when scrolling to it you can use animation-timeline : scroll(). Here I added a new animation frame with the animation*timeline for scroll, added also a div (called .toscroll just to allow page scroll). Also added a window event listener for scroll to remove this class .next-gen-agency and replace it with onscroll .class

    function isInViewport(element) {
        const rect = element.getBoundingClientRect();
        return (
          rect.top >= 0 &&
          rect.left >= 0 &&
          rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
          rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );
      }
      const startAnimation = (entries, observer) => {
        entries.forEach(entry => {
          entry.target.classList.toggle("slideIn", entry.isIntersecting);
        });
      };
    
      const observer = new IntersectionObserver(startAnimation);
      const options = { root: null, rootMargin: '0px', threshold: 1 };
    
      const elements = document.querySelectorAll('.next-gen-agency');
      elements.forEach(el => {
        console.log("el = ", el);
        observer.observe(el, options);
      });
    
    
        const theSection = document.getElementById('the-section')
      window.addEventListener('scroll',()=>{
        theSection.classList.remove('next-gen-agency')
        theSection.classList.add('onscroll')
      })
    @keyframes slideIn {
      0% {
        opacity: 0;
        transform: translateY(50px);
      }
      100% {
        opacity: 1;
        transform: translateY(0);
      }
    }
    
    @keyframes onScrollSlideIn {
      0% {
        opacity: 1;
        transform: translateY(50px);
      }
      50% {
        opacity: 0.15;
      }
      100% {
        opacity: 1;
        transform: translateY(0);
      }
    }
    
        .next-gen-agency {
          animation: slideIn 1.5s ease-in-out forwards;
          opacity: 1;
          background-color: #E4D8D3;
          margin-top: 8rem;
        }
    
        .onscroll{
          animation: onScrollSlideIn 1.5s ease-in-out backwards;
          animation-timeline: scroll();
          opacity: 1;
          background-color: #E4D8D3;
          margin-top: 8rem;
        }
    
        .agency-stats {
          background-image: linear-gradient(to right,
            #00e0ff,
            #3eb6d4);
          -webkit-background-clip: text;
          background-clip: text; color: transparent;
        }
    
        .toscroll{
          margin-top: 200px;
          height: 120vh;
        }
    <section class="next-gen-agency" id="the-section">
        <div class="container" style="display: flex; justify-content: center; align-items: center;">
          <div style="max-width: 70rem;" >
            <div style="display: flex; flex-direction: column; gap: 2rem; margin-top: 2rem;">
              <h1
                style="font-size: 4rem; font-weight: bold; background-image: linear-gradient(to right, #00e0ff, #ff007a); -webkit-background-clip: text; background-clip: text; color: transparent;">
                The Next Generation Agency.
              </h1>
              <!-- <p style="max-width: 40rem; font-size: 1.25rem; color: #c21f71">
                Our team of experts at Strive Now Management use a specialized approach to cater to your unique needs. We
                prioritize your success by understanding your goals and tailoring our strategies to help you thrive on the
                platform.
              </p> -->
              <div class="stats-div" style="display: flex; justify-content: center; align-items: center; gap: 3rem;">
                <div style="display: flex; flex-direction: column; align-items: center;">
                  <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">60+</h2>
                  <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">ACCOUNTS MANAGED</p>
                </div>
                <div class="stats-div" style="display: flex; flex-direction: column; align-items: center;">
                  <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">25+</h2>
                  <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">BRAND COLLABORATIONS</p>
                </div>
                <div class="stats-div" style="display: flex; flex-direction: column; align-items: center;">
                  <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">£100k+</h2>
                  <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">TOTAL EARNINGS</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
        <div class="toscroll">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quas explicabo officiis harum velit sed culpa voluptatum nihil veniam consectetur. Nam ipsa impedit labore delectus placeat quidem, non, dicta tenetur consequatur quas ipsum expedita. Vitae laborum odio, minus sint eius repellendus ut culpa error officiis exercitationem maxime tenetur quasi iure nemo modi. Possimus asperiores ab error sed dolor eum iure autem nobis, atque incidunt laboriosam rerum eveniet ipsum natus deleniti cupiditate vel maxime, excepturi alias recusandae reiciendis? Iusto expedita cum esse.</div>
    Login or Signup to reply.
  2. The slideIn class needs to be there to start with so the element shows on load, but the animation needs to be applied only when that class is set, not in the element all the time [otherwise it will run just the once].

    Also, the threshold being 1 means that the element won’t show at all on less tall viewports, so for the sake of being able to see it in the snippet system I’ve put it down to 0.2. You may like to think thro’ what you want it to look like when the whole element wont fit in the viewport.

    Note: I don’t know why there is a function isInViewport so I’ve removed it.

    const startAnimation = (entries, observer) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          entry.target.classList.add("slideIn");
        } else {
          entry.target.classList.remove("slideIn");
        }
      });
    };
    
    const options = {
      root: null,
      rootMargin: '0px',
      threshold: 0.2
    };
    const observer = new IntersectionObserver(startAnimation, options);
    
    const elements = document.querySelectorAll('.next-gen-agency');
    elements.forEach(el => {
      observer.observe(el, options);
    });
    @keyframes slideIn {
      0% {
        opacity: 0;
        transform: translateY(50px);
      }
      100% {
        opacity: 1;
        transform: translateY(0);
      }
    }
    
    .next-gen-agency {
      opacity: 0;
      background-color: #E4D8D3;
      margin-top: 8rem;
    }
    
    .slideIn {
      animation: slideIn 1.5s ease-in-out forwards;
    }
    
    .agency-stats {
      background-image: linear-gradient(to right, #00e0ff, #3eb6d4);
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
    }
    <section class="next-gen-agency" class="slideIn">
      <div class="container" style="display: flex; justify-content: center; align-items: center;">
        <div style="max-width: 70rem;">
          <div style="display: flex; flex-direction: column; gap: 2rem; margin-top: 2rem;">
            <h1 style="font-size: 4rem; font-weight: bold; background-image: linear-gradient(to right, #00e0ff, #ff007a); -webkit-background-clip: text; background-clip: text; color: transparent;">
              The Next Generation Agency.
            </h1>
            <!-- <p style="max-width: 40rem; font-size: 1.25rem; color: #c21f71">
              Our team of experts at Strive Now Management use a specialized approach to cater to your unique needs. We
              prioritize your success by understanding your goals and tailoring our strategies to help you thrive on the
              platform.
            </p> -->
            <div class="stats-div" style="display: flex; justify-content: center; align-items: center; gap: 3rem;">
              <div style="display: flex; flex-direction: column; align-items: center;">
                <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">60+</h2>
                <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">ACCOUNTS MANAGED</p>
              </div>
              <div class="stats-div" style="display: flex; flex-direction: column; align-items: center;">
                <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">25+</h2>
                <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">BRAND COLLABORATIONS</p>
              </div>
              <div class="stats-div" style="display: flex; flex-direction: column; align-items: center;">
                <h2 class="agency-stats" style="font-size: 2.5rem; font-weight: bold;">£100k+</h2>
                <p class="agency-stats" style="font-size: 1rem; font-weight: bold;">TOTAL EARNINGS</p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
    <section style="height:300vh;"></section>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search