42

I'm trying to create a news ticker with horizontal text that scrolls continuously without a break between loops. Ideally, the solution would be pure css/html, but I don't know if that's possible. Here's my rudimentary attempt so far: http://jsfiddle.net/lgants/ncgsrnza/. Note that the fiddle contains an unwanted break between each loop.

<p class="marquee"><span>This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text</span></p>


    .marquee {
        margin: 0 auto;
        white-space: nowrap;
        overflow: hidden;
    }
    
    .marquee span {
        display: inline-block;
        padding-left: 100%;
        animation: marquee 5s linear infinite;
    }
0

4 Answers 4

88

You could try having two marquees and set one of them with a delayed animation of 2.5s which is half the time of the full animation (5s).

.marquee {
  margin: 0 auto;
  white-space: nowrap;
  overflow: hidden;
  position: absolute;
}

.marquee span {
  display: inline-block;
  padding-left: 100%;
  animation: marquee 5s linear infinite;
}

.marquee2 span {
  animation-delay: 2.5s;
}

@keyframes marquee {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-100%, 0);
  }
}
<p class="marquee">
  <span>This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text -&nbsp;</span>
</p>
<p class="marquee marquee2">
  <span>This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text -&nbsp;</span>
</p>

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

5 Comments

Just a comment: there is no need to duplicated the keyframes (marquee2) for this concept to work.
If the text is too short you can continue to duplicate the marquees and adjust the animation delays. Alternatively you can use js to remove/add the class with the animation at specific time intervals but @lgants wanted pure css/html.
I was able to make the text start from the left by adding a negative animation delay to the first span and setting the second span to have no delay. .marquee1 span { animation-delay: -2.5s; } .marquee2 span { animation-delay: 0s; }
I just want to add my 5c here: I have checked a lot of solutions for this issue, and my verdict is that this is the best one in terms of the visual quality you get. As for the code, the two first lines in the .marquee selector are debatable. margin is purely for style purposes. And white-space is more suitable in the .marquee span class. Another thing is that this solution does not suffer from too much text in span. On the contrary, with short text, you may see a gap. So don't be shy – add as much text as makes you feel safe :)
so the key thing is to repeat the text to fill out the empty space
32

This is similar to above answer. I have taken it from the official website of Next.js. They have used this with SVGs to make a slider to show which popular companies are using their framework.

.wrapper {
  max-width: 100%;
  overflow: hidden;
}

.marquee {
  white-space: nowrap;
  overflow: hidden;
  display: inline-block;
  animation: marquee 10s linear infinite;
}

.marquee p {
  display: inline-block;
}

@keyframes marquee {
  0% {
    transform: translate3d(0, 0, 0);
  }
  100% {
    transform: translate3d(-50%, 0, 0);
  }
}
<div class="wrapper">
  <div class="marquee">
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat, ante eu bibendum tincidunt, sem lacus vehicula augue, ut suscipit.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat, ante eu bibendum tincidunt, sem lacus vehicula augue, ut suscipit.
    </p>
  </div>
</div>

4 Comments

This depends on the width of the container. If width is high, text will suddenly show up when in middle of page.
@MartinMeeser You're right. But that depends on how fast a particular (user's) browser can render the moving paragraph (especially just before the X-axis translate). And it can be prevented to some extent by slowing down the animation.
Much better than the verified answer!!!
Thanks for posting this. I used the mark-up and css basically as-is to power a top-banner ticker widget for a BigCommerce client.
6

I was using the answers on this post to make mine, and ended up with a different version making use of flexbox.

You need at least 2 text nodes and they must have equal length in order for them to have the same width, otherwise they will move at a different pace. You could instead specify a width for the .marquee, but there would likely be irregular gaps between texts.

/* Core functionality */
#animated-text-strip{
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  overflow: hidden;
}
#animated-text-strip .marquee {
  white-space: nowrap;
  animation: marquee 5s linear infinite;
  max-width: none;
}

@keyframes marquee {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-100%, 0);
  }
}

/* Styles for the sake of the demonstration */
#animated-text-strip{
  background:black;
  padding: 1rem 0;
}
.marquee{
  font-family: 'Open Sans', sans-serif;
  font-size: 2rem;
  font-weight: 900;
  text-transform: uppercase;
  color: white;
}
<div id="animated-text-strip">
  <span class="marquee">Text length has to be equal&nbsp;</span>
  <span class="marquee">Text length has to be equal&nbsp;</span>
  <span class="marquee">Text length has to be equal&nbsp;</span>
</div>

How many nodes you need will depend on the length of your text. There must always be one node more than the nodes it takes to fill the container width. So if your node takes 50% of the width, you will need 2 to fill the width, and then an extra one that will exist outside the container boundaries and will appear in screen during the animation.

Notice that max-width needs to be set to none. Otherwise if the text is longer than the container width the nodes will overlap.

Comments

-1

.marquee {
  margin: 0 auto;
  white-space: nowrap;
  overflow: hidden;
  position: absolute;
}

.marquee span {
  display: inline-block;
  padding-left: 100%;
  animation: marquee 14s linear infinite;
}

.marquee2 span {
  animation-delay: 0s;
}

@keyframes marquee {
  0% {
    transform: translate(0, 0);
  }
   25% {
    transform: translate(-25%, 0);
  }
   50% {
    transform: translate(-50%, 0);
  }
     75% {
    transform: translate(-75%, 0);
  }
  100% {
    transform: translate(-100%, 0);
  }
}
<p class="marquee">
  <span>This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text - This is text -&nbsp;</span>
</p>

1 Comment

Thank you for your interest in contributing to the Stack Overflow community. This question already has a few answers—including at least one that has been validated by the community. It would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?

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.