How to Make a CSS Marquee Without the Deprecated Marquee Tag

The old <marquee> element can still appear in legacy code, but it is obsolete and should not be the foundation of a new component. A modern marquee uses normal semantic HTML plus CSS animation.

Start with a clipped viewport

The outer element defines the visible area. The inner track moves across it.

<div class="marquee" aria-label="Shipping is free this weekend">
  <span class="marquee__text">Shipping is free this weekend</span>
</div>
.marquee { overflow: hidden; }
.marquee__text {
  display: inline-block;
  min-width: 100%;
  white-space: nowrap;
  animation: marquee-left 14s linear infinite;
}
@keyframes marquee-left {
  from { transform: translateX(100%); }
  to { transform: translateX(-100%); }
}
.marquee:hover .marquee__text,
.marquee:focus-within .marquee__text { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .marquee__text { animation: none; white-space: normal; }
}

Seamless continuous marquees

A single message leaves a gap while it exits and re-enters. For a continuous logo strip or ticker, duplicate the presentation track and animate exactly one copy-width. The duplicated copy should be hidden from assistive technology so the message is not announced twice.

Avoid speed settings that mean different things

Some plugins label a number as “speed” even though it is really duration. A clearer UI says “Duration: 12 seconds” and explains that a larger value moves more slowly. If you calculate pixels per second instead, display that unit explicitly.

Pause and reduced motion

Pause-on-hover is helpful but keyboard users also need a way to stop movement. For informational tickers, include a visible pause button. Always provide a prefers-reduced-motion fallback that removes continuous motion.

The Marquee Text Generator creates this pattern visually and outputs the HTML and CSS separately or together.

More guides