Overview
Marquee tickers are simple in concept (move a strip of content sideways) and full of small failure modes: how do you make the loop seamless, what happens on a vertical-axis variant, what happens to screen readers when content scrolls under them. This pattern documents axis ownership (X vs Y), duplicate-track accessibility (the dupe stays aria-hidden so AT users hear the content once), and a static prefers-reduced-motion fallback that keeps the full content visible without scroll.
When to use it
Reach for marquee tickers when you have a stream of equal-weight items that benefit from constant motion — partner logos, stock prices, news headlines, social proof bars. Skip them for paragraphs of body copy; scrolling text readers cannot pause is hostile. Skip them in any context where the content needs to be acted on (CTAs, form fields, error messages) — users cannot click a moving target comfortably.
How it works
The track contains two copies of the same content row, side by side. The track animates transform: translateX(0) to translateX(-50%) on infinite loop — at -50% the view shows the start of the second copy, which is identical to the start of the first copy, so the loop wraps without a visible seam. The vertical variant swaps translateX for translateY and orients the track as a flex column. The hover-pause ribbon variant pauses the animation on :hover + :focus-within so users can read individual items.
Production gotchas
The second copy MUST be aria-hidden="true" or screen readers announce every item twice. translateX(-50%) depends on the track width being exactly the sum of two identical content widths — if items have variable widths or gaps differ between the original and the duplicate, the seam will visibly hop. Animating left or margin-left instead of transform forces layout on every frame — always use transform for the marquee. iOS Safari throttles offscreen marquee animations aggressively in low power mode; the loop will appear paused, which is actually desirable behavior.
Accessibility
Live scrolling text is one of the worst patterns for users with cognitive or vestibular disabilities, so the hover-pause variant ships as the recommended default for interactive contexts. Under prefers-reduced-motion: reduce the animation stops and the duplicate track switches to display: none so the single non-scrolling row remains. The duplicate is always aria-hidden, regardless of motion preference.
References
Implementation depth
The hard part is ownership of axes. Let vertical scroll decide progress while the ticker track owns horizontal translation; mixing both concerns in one element makes the marquee feel like it slips under the user instead of responding to scroll.
The duplicate track is still an accessibility boundary. Hide the duplicate with aria-hidden, keep the readable source in DOM order, and freeze the track under reduced motion so scroll remains a navigation cue rather than a forced animation.