Skip to content
Knsept
Free playbook

Seamless marquee

An endless scrolling strip of logos or tags. Pure CSS loop with a pause button; slower, never stopped, with reduced motion.

CSSUI Widgets Updated Oct 23, 2026
Live demo Reduced motion is on, so effects are toned down
<div class="marquee-wrap">
  <div class="marquee" aria-label="Tools we use">
    <ul class="marquee-track">
      <li>Astro</li><li>TypeScript</li><li>Cloudflare</li><li>CSS</li>
      <li>Vite</li><li>Node</li><li>SQLite</li><li>Git</li>
    </ul>
  </div>
  <button class="marquee-toggle" type="button" aria-pressed="false">Pause</button>
</div>

The trick is duplication: the track holds every item twice, and the animation slides it exactly half its own width. At that point the second copy sits where the first one started, so the loop restarts on an identical frame and you never see a seam. The - 6px accounts for half of the gap between the two copies.

The mask fades the edges, and hovering or focusing inside pauses the strip so people can read it. Anything that moves on its own for more than five seconds should also have a way to stop it (WCAG 2.2.2), which is what the Pause button is for. The copies get aria-hidden="true", so screen readers read the list once.

With reduced motion on, the strip keeps moving at a much slower pace instead of stopping. Change --marquee-duration to tune the speed.

More from the library

Text effects live

Text scramble

A heading that "decodes" from random characters into the real words, one letter at a time.

Text effects live

Shimmer text

A headline with a band of light sweeping across it, using background-clip text. Pure CSS, a few lines.

Text effects live

Typewriter rotator

Types, pauses, deletes, and cycles through phrases with a blinking caret.