Skip to content
Advertisement

JavaScript animation not working properly

I have an animation that I’m using from codepen that worked well until a little while back when I was changing some things around. The animation code itself still works fine and is unchanged, but whatever I changed around in my HTML seems to have stopped it from functioning properly. Here’s the animation code:

const cards = document.querySelectorAll(".card");

function isElementInViewport(el) {
  const rect = el.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (
    window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth));

}

function isCardVisible() {
  for (card of cards) {
    isElementInViewport(card) ?
    card.classList.add("isVisible") :
    card.classList.remove("isVisible");
  }
}

document.addEventListener("DOMContentLoaded", isCardVisible);
window.addEventListener("scroll", isCardVisible);
window.addEventListener("resize", isCardVisible);

And here’s my HTML and corresponding CSS:

<div class="wrapper">
  <div class="card">
    <img src="./main/elise.jpeg" />
  </div>
  <div class="card">
    <img src="./main/gabrielle.jpg" />
  </div>
  <div class="card">
    <img src="./main/soccer.jpeg" />
  </div>
  <div class="card">
    <img src="./main/lauren.jpg" />
  </div>
</div>

<script  src="./script.js"></script>
/* cards */
.wrapper {
  width:  auto;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  -ms-overflow-style: none;  /* IE and Edge */
  scrollbar-width: none;  /* Firefox */
  overflow-y: hidden;
}

.card {
  margin: 0 3vw;
  width: auto;
  height:  auto;
  flex-shrink: 0;
  box-sizing: border-box;
  position: relative;
  border-radius: 3px;
  border: 2px solid #000;
  display: flex;
  justify-content: space-between;
  flex-direction: column;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
}
.card-title {
  transition: 0.3s;
  text-align: center;
  font-family: "Space Mono", monospace;
  margin: 2vw 0 0;
  font-size: 2.8vw;
  opacity: 0;
  transform: scale(0.7);
}
.card:last-child:after {
  content: "";
  width: 6vw;
  position: absolute;
  height: 100%;
  right: -6vw;
  top: 0;
}
.card img {
  max-width: 70%;
  max-height: 50vh;
  opacity: 0;
  margin: auto;
  display: block;
  transition: 0.35s;
  transform: rotate(6deg) translate(0, 40px) scaleY(0.6);
}
.card.isVisible img {
  max-width: 100%;
  opacity: 1;
  transform: none;
}
.card.isVisible .card-title {
  opacity: 1;
  transform: none;
  transition-delay: 0.1s;
}
.card:first-child {
  margin-left: 6vw;
}

How do I keep the animation as it’s meant to function, while keeping the same exact format that I have the webpage as right now? Here’s the original animation from codepen for reference: https://codepen.io/knyttneve/pen/EGyQqN

If you need to see more of the code for the webpage, please let me know and I will happily supply it.

Advertisement

Answer

You do that by using intersection observer (IO) instead of listening to scroll events. IO let’s you observe elements on a page and react when they come into view or leave the view (intersecting with the viewport) or are intersecting with each other.

You can set threshold, meaning you specify how much of an element has to be intersecting to trigger the callback function.

Prepared a snipped for you, used this article as a reference

const myImgs = document.querySelectorAll('.card');

const options = {
  rootMargin: '0px',
  threshold: 1
};

let observer = new IntersectionObserver((entries) => {
   console.log(entries);
   entries.forEach(entry => {
    if(entry.isIntersecting ) {
       entry.target.classList.add('isVisible');
    } else {
      entry.target.classList.remove('isVisible');
    }
   });
}, options);

myImgs.forEach(image => {observer.observe(image)} );
/* cards */
.wrapper {
  width:  auto;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  -ms-overflow-style: none;  /* IE and Edge */
  scrollbar-width: none;  /* Firefox */
  overflow-y: hidden;
}

.card {
  margin: 0 3vw;
  width: auto;
  height:  auto;
  flex-shrink: 0;
  box-sizing: border-box;
  position: relative;
  border-radius: 3px;
  border: 2px solid #000;
  display: flex;
  justify-content: space-between;
  flex-direction: column;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.1);
}
.card-title {
  transition: 0.3s;
  text-align: center;
  font-family: "Space Mono", monospace;
  margin: 2vw 0 0;
  font-size: 2.8vw;
  opacity: 0;
  transform: scale(0.7);
}
.card:last-child:after {
  content: "";
  width: 6vw;
  position: absolute;
  height: 100%;
  right: -6vw;
  top: 0;
}
.card img {
  max-width: 70%;
  max-height: 50vh;
  opacity: 0;
  margin: auto;
  display: block;
  transition: 0.35s;
  transform: rotate(6deg) translate(0, 40px) scaleY(0.6);
}
.card.isVisible img {
  max-width: 100%;
  opacity: 1;
  transform: none;
}
.card.isVisible .card-title {
  opacity: 1;
  transform: none;
  transition-delay: 0.1s;
}
.card:first-child {
  margin-left: 6vw;
}
<div style="height: 200vh"> </div>
<div class="wrapper">
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Pikachu</h2>
  </div>
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Alakazam</h2>
  </div>
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Arbok</h2>
  </div>
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Bulbasaur</h2>
  </div>
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Pikachu</h2>
  </div>
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Alakazam</h2>
  </div>
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Arbok</h2>
  </div>
  <div class="card">
    <img src="https://via.placeholder.com/150" />
    <h2 class="card-title">Bulbasaur</h2>
  </div>
</div>
<div style="height: 200vh"></div>
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement