Overview
A CSS marquee ticker creates seamless infinite scroll via duplicated content tracks (aria-hidden on the duplicate). The track animates translateX from 0 to -50% on infinite loop; at -50% the view shows the start of the duplicate copy, identical to 0%, so the seam is invisible.
When to use it
Reach for marquees on partner-logo bars, social-proof ribbons, stock tickers, news headline strips. Skip them for body content where users need to read the text — scrolling that the user cannot pause is hostile. Always respect prefers-reduced-motion and offer a pause affordance for live tickers.
How it works
Render the content twice inside a single track wrapper (the second copy with aria-hidden="true" so screen readers do not announce duplicates). Set display: flex; width: max-content on the track and animate transform: translateX(0) → translateX(-50%) on linear infinite loop. At -50% the leftmost edge of the duplicate copy aligns exactly with what was the leftmost edge of the original at the start of the cycle — so the seam wraps without any visible jump. Use animation-duration computed from total track width to keep speed consistent across content widths.
This is the key difference between a production marquee and the obsolete <marquee> element: the DOM keeps one readable source track, the visual layer gets a duplicate track, and the duplicate is hidden from assistive tech. Searchers looking for an accessible marquee usually need that exact duplicated-track contract, not just a moving row of text.
Production gotchas
Forgetting width: max-content on the track causes the content to wrap or compress, breaking the seam. The duplicated content must be byte-identical — any difference (even a single random ID) breaks the visual loop. Pause-on-hover via :hover { animation-play-state: paused } is the friendly default for partner logos but the wrong default for live tickers where you don’t want accidental hovers to halt updates. Mobile Safari has historical bugs with sub-pixel rendering on long-running linear animations — if the marquee jitters every few seconds, add will-change: transform to force a dedicated compositor layer.
Accessibility
WCAG 2.2.2 requires that any auto-scrolling content users cannot pause be limited to 5 seconds — for marquees that exceed that, you must provide a pause control or honor prefers-reduced-motion. Under reduced motion the marquee should stop entirely and render a static snapshot. Mark the duplicate copy with aria-hidden="true" so screen readers do not announce content twice. Pause the animation on :focus-within as well so keyboard users reading content inside the track get a stable view.
References
Implementation depth
A seamless marquee depends on identical source and duplicate tracks. The track moves to -50%, where the duplicate begins at the same visual position the original had at 0%, so the loop can restart without a jump.
The duplicate must be hidden from assistive technology and the motion must be pausable. For live or long-running tickers, hover, focus-within, and reduced motion all need a stable readable state.