Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setInterval() Method creating strange overlap

As I was playing around trying to build a simple text carousel, I came across an issue I am having a difficult time understanding.

The layout is simple. I have a wrapper and the text I want the carousel to cycle through.

The issue I am having, however, seems as far as I can tell to be coming from the setInterval method. After the animation cycles through all the text and returns to the beginning, there is a strange overlap between the first and second text that is displayed. The first text will animate, but then will return to replace the second text temporarily.

Any help in understanding what is causing this error to render in this way would be greatly appreciated.

let animateSlide = setInterval(moveSlide, 1200);

function moveSlide() {
  let carousel = document.getElementById("wordCarousel");
  let firstSlide = carousel.children[0];
  let createID = document.createAttribute("id");

  createID.value = "active";

  firstSlide.setAttributeNode(createID);

  carousel.appendChild(carousel.firstChild);

  carousel.children[carousel.children.length - 1].removeAttribute("id");
}
/* Carousel Styles */

#wordCarousel {
  height: 36px;
  overflow: hidden;
}

  .carouselSlide {
    color: #555;
    font-size: 36px;
  }

#active {
  margin-top: 0px;
  animation-name: example;
  animation-duration: 1.2s;
  animation-timing-function: ease;
}

@keyframes example {
  from {
    margin-top: 0px;
  }
  to {
    margin-top: -40px;
  }
}
<div id="wordCarousel">
  <div class="carouselSlide">
    Item 1
  </div>
  <div class="carouselSlide">
    Item 2
  </div>
  <div class="carouselSlide">
    Item 3
  </div>
  <div class="carouselSlide">
    Item 4
  </div>

</div>
like image 651
Just Trying to Learn JS Avatar asked Nov 15 '20 10:11

Just Trying to Learn JS


1 Answers

Don't rely on setInterval when dealing with CSS animation. You will never have a perfect synchronization. Better consider events like animationiteration/animationend/animationstart

Here is a better idea will less of code an easier to handle.

let carousel = document.querySelector('#wordCarousel div');

carousel.addEventListener('animationiteration', () => {
  carousel.appendChild(carousel.children[0]);
});
#wordCarousel {
  height: 36px;
  overflow: hidden;
}

.carouselSlide {
  color: #555;
  font-size: 36px;
  line-height:100%; /* line-height will make sure the height is equal to 36px, font-size alone isn't enough  */
}

#wordCarousel > div {
  height:100%;
  animation: example 1s infinite;
}

@keyframes example {
  to {
    transform: translateY(-100%);
  }
}
<div id="wordCarousel">
  <div>
    <div class="carouselSlide">
      Item 1
    </div>
    <div class="carouselSlide">
      Item 2
    </div>
    <div class="carouselSlide">
      Item 3
    </div>
    <div class="carouselSlide">
      Item 4
    </div>
  </div>
</div>
like image 93
Temani Afif Avatar answered Nov 19 '22 05:11

Temani Afif