0

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>

5
  • You can check this CSS only suggestion. Very smooth because no JS involved Commented Jan 2 at 3:07
  • @LãNgọcHải It's not possible to make it responsive for various width and text. Use JavaScript to make dynamic CSS code depending on browser width. If you don't need responsive and dynamic content then better use CSS only. Commented Jan 2 at 3:56
  • @AmirABD what? CSS totally can deal with responsiveness (in current context). Please elaborate if JS usage is better. Commented Jan 2 at 4:01
  • @LãNgọcHải Can you please explain, how can we make it responsive? The example you suggested is fixed not responsive. Is it possible to make continuous responsive dynamic content @keyframes animations with CSS only? No pause or jump from 100% to 0%? Maybe there are some ways that I don't know. Commented Jan 2 at 4:15
  • 1
    @AmirABD it's just an example with hard code, you can totally use %, vw and media query to make it responsive. Have you tried the code in the suggestion? Commented Jan 2 at 4:16

2 Answers 2

1

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%));
}

}

Sign up to request clarification or add additional context in comments.

Comments

-1

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>

6 Comments

“You need to use JavaScript” - could you explain why?
To handle animation start and animation end for making continuous time line without pause or jump from 100% to 0% on keyframes loop.
@AmirABD That... doesn't sound right. We should be able to do that with CSS only
I've just run your snippet, on both IOS and Windows11. It has a strange effect where the start of the banner ('AUTHENTIC') sometimes gets 'stuck' part way across and the banner carries on scrolling to the left of it. It's even more noticeable if you use the original timing of 20s (2000ms).
Ah, thanks, I should have spotted that. You may like to put a resize function in there as going full page on the snippet makes it look odd.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.