Reputation: 896
The answers to How can I create a marquee effect? show how to create a marquee effect, but it leaves a lot of empty space at the end of each iteration of the marquee.
Is there a way to achieve a smooth <marquee></marquee>
effect, using CSS, that doesn't have this empty space?
I have a lot of small elements, which look a bit like Stack Overflow's blue tags, that exclusively fill the content of the marquee, as opposed to one continuous body or a wall of text.
Upvotes: 15
Views: 56409
Reputation: 1113
In the example you mention, since the content goes from x=0 to x=-100% it will always leave a gap at the end while the animation starts again.
The first step of this solution relies on duplicating the content. But if we go from x=0 to x=-100, we still have the same issue (despite the content is shown a little bit longer as it is duplicated). After it finishes the two rounds of displaying the main content, a gap (twice the size of the main content) shows up again.
So we solve it going from x=0 to x=-50. The animation finishes when it reaches the half of the whole content, but nothing is missing since the second half of the whole content is the same one as the main content.
When the animation finishes (i.e. x=-50%) it will start again. But as the filling half is the same as the one that is about to start, it will look like it is going one after another.
Hopefully code explains this better:
.marquee {
--duration: 20;
background-color: #ddd;
width: max-content;
white-space: nowrap;
display: flex;
gap: 1rem;
padding-left: 1rem;
animation: marquee calc(var(--duration) * 1s) linear infinite;
}
@keyframes marquee {
to {
transform: translateX(-50%);
}
}
.main{
background-color: yellow;
}
.duplicated{
background-color: orange;
}
<b>Solution</b>
<p class="marquee">
<span>this is a simple marquee</span>
<span>with a very long text</span>
<span>that I will animate using css</span>
<span>I am making this long enough</span>
<span>so so long long</span>
<span aria-hidden="true">this is a simple marquee</span>
<span aria-hidden="true">with a very long text</span>
<span aria-hidden="true">that I will animate using css</span>
<span aria-hidden="true">I am making this long enough</span>
<span aria-hidden="true">so so long long</span>
</p>
<b>Visual aid</b>
<br/>
<span class="main">main content</span>
<span class="duplicated">duplicated content</span>
<p class="marquee visual-aid">
<span class="main">this is a simple marquee</span>
<span class="main">with a very long text</span>
<span class="main">that I will animate using css</span>
<span class="main">I am making this long enough</span>
<span class="main">so so long long</span>
<span class="duplicated" aria-hidden="true">this is a simple marquee</span>
<span class="duplicated" aria-hidden="true">with a very long text</span>
<span class="duplicated" aria-hidden="true">that I will animate using css</span>
<span class="duplicated" aria-hidden="true">I am making this long enough</span>
<span class="duplicated" aria-hidden="true">so so long long</span>
</p>
Upvotes: 1
Reputation: 3497
If the marquee is big enough, you can swap one of the collections at mid animation.
This is as far as you can get with CSS alone, I think
.marquee {
width: 100%;
height: 80px;
margin: 0 auto;
overflow: hidden;
white-space: nowrap;
border: 1px solid blue;
}
.marquee-content {
display: inline-block;
margin-top: 5px;
animation: marquee 15s linear infinite;
}
.item-collection-1 {
position: relative;
left: 0%;
animation: swap 15s linear infinite;
}
@keyframes swap {
0%, 50% {
left: 0%;
}
50.01%,
100% {
left: 100%;
}
}
.marquee-content:hover {
animation-play-state: paused
}
.item1 {
display: inline-block;
height: 70px;
width: 140px;
background: cyan;
vertical-align: top;
margin-left: 15px;
}
.item2 {
display: inline-block;
height: 70px;
width: 100px;
background: magenta;
vertical-align: top;
margin-left: 15px;
line-height: 14px;
}
/* Transition */
@keyframes marquee {
0% {
transform: translateX(0)
}
100% {
transform: translateX(-100%)
}
}
<div class="marquee">
<div class="marquee-content">
<span class="item-collection-1">
<span><img src="https://cdn.sstatic.net/Sites/stackoverflow/img/[email protected]" height="80"></span>
<span class="item1"></span>
<span><img src="https://cdn.sstatic.net/Sites/stackoverflow/img/[email protected]" height="80"></span>
<span class="item1"></span>
<span class="item1"></span>
<span class="item1"></span>
<span class="item1"></span>
</span>
<span class="item-collection-2">
<span class="item2"></span>
<span class="item2"></span>
<span class="item2"></span>
<span class="item2"></span>
<span class="item2"></span>
<span class="item2"></span>
<span class="item2"></span>
<span class="item2"></span>
</span>
</div>
</div>
Upvotes: 3
Reputation: 87313
Here is a sample how you can do, and by setting the delay and duration you control the space between the texts
.marquee {
background-color: #ddd;
width: 500px;
margin: 0 auto;
overflow: hidden;
white-space: nowrap;
}
.marquee span {
display: inline-block;
font-size: 20px;
position: relative;
left: 100%;
animation: marquee 8s linear infinite;
}
.marquee:hover span {
animation-play-state: paused;
}
.marquee span:nth-child(1) {
animation-delay: 0s;
}
.marquee span:nth-child(2) {
animation-delay: 0.8s;
}
.marquee span:nth-child(3) {
animation-delay: 1.6s;
}
.marquee span:nth-child(4) {
animation-delay: 2.4s;
}
.marquee span:nth-child(5) {
animation-delay: 3.2s;
}
@keyframes marquee {
0% { left: 100%; }
100% { left: -100%; }
}
<p class="marquee">
<span>this is a</span>
<span>simple marquee</span>
<span>using css</span>
<span>only tech</span>
<span>with a delay</span>
</p>
Upvotes: 25