How can I create a marquee effect?

Fred Wu picture Fred Wu · Jan 20, 2014 · Viewed 119.6k times · Source

I'm creating a marquee effect with CSS3 animation.

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.

Answer

Fabrizio Calderan picture Fabrizio Calderan · Jan 20, 2014

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;
  white-space: nowrap;
  overflow: hidden;
  box-sizing: border-box;
}

.marquee span {
  display: inline-block;
  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 { 
    white-space: normal 
  }
  .marquee span {
    animation-iteration-count: 1;
    animation-duration: 0.01; 
    /* instead of animation: none, so an animationend event is 
     * still available, if previously attached.
     */
    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%)