Annabelle Sykes
Annabelle Sykes

Reputation: 1

CSS Keyframe Continuous Horizontal Scroll buffering on loop start

I have programmed a continuous horizontal text scroll using CSS @keyframes and two identical div tags.

The issue I am facing is when the loop starts again, there is a small, but noticeable, pause before the text scrolls again. I would like the scroll to be continuous with no pause, even whether that means to not use CSS @keyframes and instead javascript/jQuery.

My code is below.

@keyframes infiniteScroll {
  from {
    transform: translateX(0)
  }

  to {
    transform: translateX(calc(0px - 50%));
  }
}

#scrolling-header-parent-container {
  width: 100%;
  background-color: black;
  overflow-x: hidden;

  #scrolling-header-container {
    display: flex;
    width: fit-content;
    height: 8vh;
    font-size: 30px;
    align-items: center;
    overflow-x: hidden;

    animation-name: infiniteScroll;
    animation-duration: 20s;
    animation-iteration-count: infinite;
    animation-timing-function: linear;

    .scrolling-header-container-item {
      white-space: nowrap;
      color: white;
    }
  }
}
<div id="scrolling-header-parent-container">
  <div id="scrolling-header-container">
    <div class="scrolling-header-container-item">
      AUTHENTIC VIETNAMESE FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;INDIAN CUISINE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHURROS & COFFEE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;BUBBLE TEA&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;ESCAPE ROOM EXPERIENCE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;SOUFFLE PANCAKE & DESSERT CAFE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;COCKTAIL BAR&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;TAIWANESE FRIED CHICKEN&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHINESE HOTPOT&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;POLISH STREET FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;KOREAN BBQ&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;
    </div>
    <div class="scrolling-header-container-item">
      AUTHENTIC VIETNAMESE FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;INDIAN CUISINE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHURROS & COFFEE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;BUBBLE TEA&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;ESCAPE ROOM EXPERIENCE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;SOUFFLE PANCAKE & DESSERT CAFE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;COCKTAIL BAR&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;TAIWANESE FRIED CHICKEN&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHINESE HOTPOT&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;POLISH STREET FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;KOREAN BBQ&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;
    </div>
  </div>
</div>

Upvotes: 0

Views: 117

Answers (2)

AmirABD
AmirABD

Reputation: 297

You need to use JavaScript. Change timeInMiliSeconds to change speed. If you resize your browser the page need to be refreshed to create new CSS @keyframes animations fit to page size or use body.onresize event.

let timeInMiliSeconds=10000; /* animation time in milliseconds. */

let cssContainer=document.getElementById("DYNAMICcss");
let textContainer=document.querySelectorAll('.scrolling-header-container-cls');
let wid = window.innerWidth;
let timing=timeInMiliSeconds/(textContainer[0].offsetWidth-wid);
let isFirstAnime=true;

cssContainer.innerHTML="";
cssContainer.innerHTML+="<style>@keyframes init{from {left:0; }to{left:-"+((textContainer[0].offsetWidth)-wid)+"px; }}</style>";
cssContainer.innerHTML+="<style>@keyframes firstStep1{from {left:"+wid+"px; }to{left:-"+((textContainer[0].offsetWidth)-wid)+"px; }}</style>";
cssContainer.innerHTML+="<style>@keyframes firstStep2{from {left:-"+((textContainer[0].offsetWidth)-wid)+"px; }to{left:-"+(textContainer[0].offsetWidth)+"px; }}</style>";
cssContainer.innerHTML+="<style>@keyframes secondStep1{from {left:"+wid+"px; }to{left:-"+((textContainer[0].offsetWidth)-wid)+"px; }}</style>";
cssContainer.innerHTML+="<style>@keyframes secondStep2{from {left:-"+((textContainer[0].offsetWidth)-wid)+"px; }to{left:-"+(textContainer[0].offsetWidth)+"px; }}</style>";

textContainer[0].style.animation="init "+((timing*textContainer[0].offsetWidth-wid-wid)/1000)+"s 1 linear";
textContainer[1].style.left=wid+"px";

textContainer[0].onanimationend = () => {
if(isFirstAnime){
textContainer[1].style.left=wid+"px";
textContainer[1].style.animation="secondStep1 "+((timing*textContainer[0].offsetWidth)/1000)+"s 1 linear";
textContainer[0].style.animation="firstStep2 "+((timing*wid)/1000)+"s 1 linear";
isFirstAnime=false;
}
};

textContainer[1].onanimationend = () => {
if(!isFirstAnime){
textContainer[0].style.left=wid+"px";
textContainer[0].style.animation="firstStep1 "+((timing*textContainer[0].offsetWidth)/1000)+"s 1 linear";
textContainer[1].style.animation="secondStep2 "+((timing*wid)/1000)+"s 1 linear";
isFirstAnime=true;
}
};
#scrolling-header-parent-container {
   width: 100%;
   background-color: black;
   overflow: hidden;

}
    
   .scrolling-header-container-cls {
      background-color: black;
      position:fixed;
      display: flex;
      width: fit-content;
      height: 8vh;
      font-size: 30px;
      align-items: center;
      overflow: hidden;
    }
      .scrolling-header-container-item {
         overflow: hidden;
         background-color: black;
         white-space: nowrap;
         color: white;
      }
<div id="scrolling-header-parent-container">
   <div class="scrolling-header-container-cls">
      <div class="scrolling-header-container-item">
         AUTHENTIC VIETNAMESE FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;INDIAN CUISINE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHURROS & COFFEE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;BUBBLE TEA&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;ESCAPE ROOM EXPERIENCE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;SOUFFLE PANCAKE & DESSERT CAFE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;COCKTAIL BAR&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;TAIWANESE FRIED CHICKEN&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHINESE HOTPOT&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;POLISH STREET FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;KOREAN BBQ&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;
      </div>
   </div>
   <div class="scrolling-header-container-cls">
      <div class="scrolling-header-container-item">
         AUTHENTIC VIETNAMESE FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;INDIAN CUISINE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHURROS & COFFEE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;BUBBLE TEA&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;ESCAPE ROOM EXPERIENCE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;SOUFFLE PANCAKE & DESSERT CAFE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;COCKTAIL BAR&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;TAIWANESE FRIED CHICKEN&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHINESE HOTPOT&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;POLISH STREET FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;KOREAN BBQ&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;
      </div>
   </div>
</div>

<div id="DYNAMICcss"></div>

Upvotes: -1

Ryan Niswonger
Ryan Niswonger

Reputation: 36

I think that hitch is caused by the replication of the beginning state at the very end. That is, there are two identical "frames" where it loops. I had success with changing the "to" animation calculation as follows, but this might depend on the display size:

@keyframes infiniteScroll {
from {
    transform: translateX(calc(0px - 0%));
}

to {
    transform: translateX(calc(0px - 50.05%));
}

}

Upvotes: 1

Related Questions