66

I'm creating a marquee effect with CSS3 animation.

#caption {
    position: fixed;
    bottom: 0;
    left: 0;
    font-size: 20px;
    line-height: 30px;
    height:30px;
    width: 100%;
    white-space: nowrap;
    -moz-animation:  caption 50s linear 0s infinite;
    -webkit-animation:  caption 50s linear 0s infinite;
}
@-moz-keyframes caption { 
    0% { margin-left:120%; } 100% { margin-left:-4200px; }  
}
@-webkit-keyframes caption { 
    0% { margin-left:120%; } 100% { margin-left:-4200px; }  
}
<div id="caption">
    The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. the quick brown fox jumps over the lazy dog.
</div>

Now I can get the basic marquee effect, but the code is too specific for this demo.

Is there a way to avoid using specific values like margin-left:-4200px;, so that it can adapt text in any length?

Here is a similar demo: http://jsfiddle.net/jonathansampson/XxUXD/ that uses text-indent but still with specific values.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Fred Wu
  • 908
  • 1
  • 9
  • 14

4 Answers4

129

With a small change of the markup, here's my approach (I've just inserted a span inside the paragraph):

.marquee {
  width: 450px;
  margin: 0 auto;
  overflow: hidden;
  box-sizing: border-box;
}

.marquee span {
  display: inline-block;
  width: max-content;

  padding-left: 100%;
  /* show the marquee just outside the paragraph */
  will-change: transform;
  animation: marquee 15s linear infinite;
}

.marquee span:hover {
  animation-play-state: paused
}


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


/* Respect user preferences about animations */

@media (prefers-reduced-motion: reduce) {
  .marquee span {
    animation-iteration-count: 1;
    animation-duration: 0.01; 
    /* instead of animation: none, so an animationend event is 
     * still available, if previously attached.
     */
    width: auto;
    padding-left: 0;
  }
}
<p class="marquee">
   <span>
       When I had journeyed half of our life's way, I found myself
       within a shadowed forest, for I had lost the path that 
       does not stray. – (Dante Alighieri, <i>Divine Comedy</i>. 
       1265-1321)
   </span>
   </p>

No hardcoded values — dependent on paragraph width — have been inserted.

The animation applies the CSS3 transform property (use prefixes where needed) so it performs well.

If you need to insert a delay just once at the beginning then also set an animation-delay. If you need instead to insert a small delay at every loop then try to play with an higher padding-left (e.g. 150%)

Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
  • 2
    This did not work for me when I tried it on my site. I found out that there's an external resource [prefixfree.js](http://leaverou.github.io/prefixfree/prefixfree.js) that's needed. I should have noticed the (1) beside external resources on the jsfiddle page. For those who just copied the above text without going there, you'll need the prefixfree javascript file too. – Recognizer Jun 25 '14 at 14:20
  • of course, you need to add vendor prefixes where necessary. – Fabrizio Calderan Jun 25 '14 at 14:33
  • @FabrizioCalderan Thank you, but just wondering.. Is it possible to detect if the text has finished scrolling with some javascript? – NiCk Newman May 06 '15 at 21:55
  • I twisted it a little so that instead of starting on the right, it starts with the first text already positioned left. Small change: add `.marquee span { animation-delay: -7.5s; }` – Daan Nov 19 '15 at 10:38
  • 1
    @fcalderan It it possible to make the animation without trailing space? I mean the second animation start before the 1st animation is finish so that no blank space between the animation. Thank you. – Newbie009 Mar 23 '17 at 06:40
  • 1
    Very nice but if the text character gets more or less, the speed changes as well. The more text, the faster text. Is there a solution for it? @fcalderan – Yasin Okumuş Sep 28 '18 at 14:41
  • @YasinOkumuş try to increase the animation-duration – Fabrizio Calderan Sep 28 '18 at 14:44
  • This answer worked, sort of, If you are experiencing weird behaviour like: Text slows down when fully in view (even with `linear`) or: When using text-indent: -100% the text stops at ~50%. You might have the css tag: `text-align: center` on. It causes weird stuff to happen. Just wanted to add it here in case anyone had problems like I had. – Kerwin Sneijders Feb 12 '19 at 11:58
8

Based on the previous reply, mainly @fcalderan, this marquee scrolls when hovered, with the advantage that the animation scrolls completely even if the text is shorter than the space within it scrolls, also any text length takes the same amount of time (this may be a pros or a cons) when not hovered the text return in the initial position.

No hardcoded value other than the scroll time, best suited for small scroll spaces

.marquee {
    width: 100%;
    margin: 0 auto;
    white-space: nowrap;
    overflow: hidden;
    box-sizing: border-box;
    display: inline-flex;    
}

.marquee span {
    display: flex;        
    flex-basis: 100%;
    animation: marquee-reset;
    animation-play-state: paused;                
}

.marquee:hover> span {
    animation: marquee 2s linear infinite;
    animation-play-state: running;
}

@keyframes marquee {
    0% {
        transform: translate(0%, 0);
    }    
    50% {
        transform: translate(-100%, 0);
    }
    50.001% {
        transform: translate(100%, 0);
    }
    100% {
        transform: translate(0%, 0);
    }
}
@keyframes marquee-reset {
    0% {
        transform: translate(0%, 0);
    }  
}
<span class="marquee">
    <span>This is the marquee text (hover the mouse here)</span>
</span>
Mosè Bottacini
  • 4,016
  • 2
  • 24
  • 28
2

The accepted answers animation does not work on Safari, I've updated it using translate instead of padding-left which makes for a smoother, bulletproof animation.

Also, the accepted answers demo fiddle has a lot of unnecessary styles.

So I created a simple version if you just want to cut and paste the useful code and not spend 5 mins clearing through the demo.

http://jsfiddle.net/e8ws12pt/

.marquee {
    margin: 0 auto;
    white-space: nowrap;
    overflow: hidden;
    box-sizing: border-box;
    padding: 0;
    height: 16px;
    display: block;
}
.marquee span {
    display: inline-block;
    text-indent: 0;
    overflow: hidden;
    -webkit-transition: 15s;
    transition: 15s;
    -webkit-animation: marquee 15s linear infinite;
    animation: marquee 15s linear infinite;
}

@keyframes marquee {
    0% { transform: translate(100%, 0); -webkit-transform: translateX(100%); }
    100% { transform: translate(-100%, 0); -webkit-transform: translateX(-100%); }
}
<p class="marquee"><span>Simple CSS Marquee - Lorem ipsum dolor amet tattooed squid microdosing taiyaki cardigan polaroid single-origin coffee iPhone. Edison bulb blue bottle neutra shabby chic. Kitsch affogato you probably haven't heard of them, keytar forage plaid occupy pitchfork. Enamel pin crucifix tilde fingerstache, lomo unicorn chartreuse plaid XOXO yr VHS shabby chic meggings pinterest kickstarter.</span></p>
Pixelomo
  • 6,373
  • 4
  • 47
  • 57
  • Hi, thanks for the heads-up regarding safari, but one question: if you're saying you're cleaning up the extra styles... why adding "padding: 0; height: 16px; and stuff like that? Is it for some browsers to display correctly? Thank you! – Juanma Guerrero Oct 05 '20 at 01:09
  • 1
    I'm testing on Safari Version 13.1.1 and the accepted answer works fine (OSX Mojave, October 2020) – Juanma Guerrero Oct 05 '20 at 01:16
  • 3
    Feels like bullet train :D – divy3993 Feb 18 '21 at 07:13
-1

The following should do what you want.

@keyframes marquee {
    from  { text-indent:  100% }
    to    { text-indent: -100% }
}
Lars Beck
  • 3,446
  • 2
  • 22
  • 23
  • 6
    No it does not, since the parent width is considered for this: Let it scroll to the end and see that the text disappears before it is scrolled completely out of sight: http://jsfiddle.net/XxUXD/712/ – Christoph Jan 20 '14 at 12:16
  • I just up voted your comments, you're right... nobody told me it runs infinite. ;) – Lars Beck Jan 20 '14 at 12:23