Reputation: 1
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 • INDIAN CUISINE • CHURROS & COFFEE • BUBBLE TEA • ESCAPE ROOM EXPERIENCE • SOUFFLE PANCAKE & DESSERT CAFE • COCKTAIL BAR • TAIWANESE FRIED CHICKEN • CHINESE HOTPOT • POLISH STREET FOOD • KOREAN BBQ •
</div>
<div class="scrolling-header-container-item">
AUTHENTIC VIETNAMESE FOOD • INDIAN CUISINE • CHURROS & COFFEE • BUBBLE TEA • ESCAPE ROOM EXPERIENCE • SOUFFLE PANCAKE & DESSERT CAFE • COCKTAIL BAR • TAIWANESE FRIED CHICKEN • CHINESE HOTPOT • POLISH STREET FOOD • KOREAN BBQ •
</div>
</div>
</div>
Upvotes: 0
Views: 117
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 • INDIAN CUISINE • CHURROS & COFFEE • BUBBLE TEA • ESCAPE ROOM EXPERIENCE • SOUFFLE PANCAKE & DESSERT CAFE • COCKTAIL BAR • TAIWANESE FRIED CHICKEN • CHINESE HOTPOT • POLISH STREET FOOD • KOREAN BBQ •
</div>
</div>
<div class="scrolling-header-container-cls">
<div class="scrolling-header-container-item">
AUTHENTIC VIETNAMESE FOOD • INDIAN CUISINE • CHURROS & COFFEE • BUBBLE TEA • ESCAPE ROOM EXPERIENCE • SOUFFLE PANCAKE & DESSERT CAFE • COCKTAIL BAR • TAIWANESE FRIED CHICKEN • CHINESE HOTPOT • POLISH STREET FOOD • KOREAN BBQ •
</div>
</div>
</div>
<div id="DYNAMICcss"></div>
Upvotes: -1
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