Search topics
Scrolling tickers and animations that can't be paused
An announcement bar scrolls its messages sideways without end, or swaps them every few seconds, and the only way to stop it is to hold a mouse pointer over it.
animation: ticker 30s linear infinite; The problem
People who can't read moving text, or can't look away from it, have no way to stop the scrolling announcements without a mouse.
A linen shop has a thin announcement bar across the top of every page. Its three messages, free delivery over $50, an autumn sale and a new range of shirts, scroll sideways in one long line, round and round for as long as the page is open. Holding the mouse pointer over the bar pauses it, and it starts again the moment the pointer leaves. There is no button to stop it, and nothing for the keyboard to reach. Many shops show the same bar as a small slider instead: one message at a time, swapped every four seconds, with an arrow at each end. The arrows step through the messages, but the timer carries on, and again only the mouse pointer held over the bar stops it.
Success criterion 2.2.2 Pause, Stop, Hide applies to moving, blinking or scrolling information that starts by itself, lasts more than five seconds, and sits alongside other content. All three hold here, so the page needs a way for the visitor to pause, stop or hide the bar. Pausing on hover is not that way: it needs a mouse, works only while the pointer stays put, and gives keyboard, touch and voice users nothing. Understanding 2.2.2 says the same of animation that stops only while it has focus, because it ties the visitor to the moving thing. Technique F16 names scrolling content with no mechanism to pause it as a failure. The slider's arrows don't count either: they change the message, but nothing stops the rotation.
The bar sits at the top of every page, so the movement follows the visitor through the whole shop. On a phone, the bar is also where the eye lands first.
3 of 10 groups affected
- No vision (not affected)
- Low vision (affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (affected)
- Reach, strength (not affected)
- Cognitive (affected)
- Seizures (not affected)
- Limited language, cognitive and learning abilities Movement at the edge of the page pulls the eye back again and again, so people with attention difficulties can't settle on the content beside it, and people who read slowly lose each message before they finish it.
- Limited vision With a screen magnifier, only part of the bar is in view, and the words slide out of it before they can be read. Low vision readers who need to track each word can't keep up with text that moves.
- Limited manipulation The only way to stop it is to hover a mouse over it, which keyboard, switch and voice control users can't do, and which touch screens have no way to hold.
The audit finds every CSS animation that runs forever and flags it for a person to check, but it can't tell a ticker from a gently pulsing dot, or see a Pause button somewhere else on the page. Movement that a script drives frame by frame, as many carousel and ticker libraries do, never shows up as a CSS animation at all. axe reports the old <marquee> element, which still scrolls in every browser, but not the CSS that replaced it. AI fixes often add animation-play-state: paused on :hover and :focus-within, which looks like a pause but stops only while the pointer or focus stays on the bar, or turn the animation off under the reduced-motion setting and stop there, which helps only people who found that setting. A slider that swaps its messages on a timer has no animation running at all; the audit flags it only when it is marked data-autoplay="true", as many themes mark their announcement bars, or is a Swiper with autoplay on.
Try it
Try to stop the moving announcements, first with the mouse, then with Tab.
Hovering pauses it only while the pointer stays there, and Tab finds nothing that stops it. Broken 2 is the slider version: its arrows change the message, but the timer carries on. "Stop demo" is the Learn page’s own button, not the shop’s.
Broken Can you fix this?
- Free delivery on orders over $50
- Autumn sale: up to 30% off until 31 October
- New: linen shirts in five colours
Linen for every season
Washed soft, woven to last, and made in small runs.
Shop shirtsA recreated demo. The broken version is intentionally inaccessible.
The fix
Let the announcements stay still, show one at a time with Previous and Next buttons, or give them a Pause button that stops them and shows every message.
- 1Nothing moves by itself for more than five seconds unless a button beside it stops it.
- 2Pausing on hover or focus is an extra, never the way to stop it.
- 3Once still, every message can be read, in view or a button press away.
html
<div class="ticker"> <div class="ticker-track"> <ul> <li>Free delivery on orders over $50</li> <li>Autumn sale: up to 30% off until 31 October</li> <li>New: linen shirts in five colours</li> </ul> <!-- The same three messages again, so the loop has no gap. --> <ul aria-hidden="true">…</ul> </div></div>html
<!-- Or the same messages as a slider, one at a time. --><div class="notice-bar"> <button type="button" class="notice-prev"> <svg aria-hidden="true" focusable="false"><use href="#icon-previous"></use></svg> <span class="visually-hidden">Previous announcement</span> </button> <ul class="notices"> <li>Free delivery on orders over $50</li> <li hidden>Autumn sale: up to 30% off until 31 October</li> <li hidden>New: linen shirts in five colours</li> </ul> <button type="button" class="notice-next"> <svg aria-hidden="true" focusable="false"><use href="#icon-next"></use></svg> <span class="visually-hidden">Next announcement</span> </button></div>The messages stay still
<ul class="notices"> <li>Free delivery on orders over $50</li> <li>Autumn sale: up to 30% off until 31 October</li> <li>New: linen shirts in five colours</li></ul>Either bar starts moving as the page loads and never ends. The only pause is hover, the ticker's :hover rule or the slider's mouseenter, so it needs a mouse, and the bar moves on as soon as the pointer leaves. The slider's arrows change the message, but the timer carries on.
Nothing moves, so 2.2.2 has nothing to ask for, and nobody has to find a control. The messages are written once, so there is no hidden copy to keep in step, and they wrap onto a second or third line on a narrow screen instead of running off the edge. On a phone the bar grows taller as a result, so keep it to the messages that matter.
All three pass 2.2.2. Still messages cost no button and no script, and everyone can read every message, but the design gives up its movement and the bar can take two or three lines on a phone. One message at a time keeps the bar to one line on any screen, at the cost of two buttons and a little script, and the later messages are seen only by people who press Next. The Pause button keeps the movement the design was built around, at the cost of a button, a little script and a bar that moves for everyone until they find it. Choose still messages when they fit, one at a time when space is tight, and the Pause button when the movement is part of the brand.
Pausing on hover is a kindness to mouse users reading a message, and it can stay, but it is never the mechanism. The same goes for pausing while the bar has focus: Understanding 2.2.2 rules out a pause that lasts only as long as focus stays on the moving content.
Starting stopped under the reduced-motion setting, as the Pause button fix does, helps the people who set it, but it is no substitute for the button. Many people who are distracted by movement never find that setting, or use a computer they can't change, and 2.2.2 asks for a mechanism on the page. The script sets the starting state rather than a media query, so the button and the bar always agree, and pressing Play is the visitor's own request to see it move.
The Pause button is an icon button, so it needs what any icon button needs: a name in hidden text or aria-label, an icon with 3:1 contrast against the bar, a size of at least 24 by 24 pixels, a visible focus ring, and an icon and name that change together. Put it before the moving content, not after the last message, and keep the choice for the rest of the visit, for example in sessionStorage, so the bar does not start again on every page.
The copy of the messages that makes the loop seamless needs aria-hidden="true", or screen readers read every message twice. If the messages are links, use inert instead, which also takes the copies out of the tab order; aria-hidden on focusable links leaves Tab stops that read as nothing.
Motion that stops by itself within five seconds needs no control. An entrance animation, or an animated GIF exported to loop only a few times, passes as long as it is over in five seconds. A ticker can't meet that and still show its messages, so it needs one of the fixes above.
If a slider keeps its timer, give the message list aria-live="off" while it turns and "polite" once it is stopped, or every change interrupts screen reader users.
A close button that hides the bar also passes, since 2.2.2 allows pause, stop or hide. It is a good extra, but on its own it leaves the people who most need the delivery and sale details with the choice of reading moving text or not reading it at all.
The same failure shows up wherever something moves by itself alongside the content. Each takes the same fixes, stay still or a stop button beside it.
- Logo strips and "marquee" rows of products that slide sideways without end.
- Animated GIF, WebP and Lottie illustrations that loop for more than five seconds.
- Background videos, which need their own Pause button even when muted.
- The old
<marquee>element, which has no way to pause and should be replaced, not styled.
Auto-advancing carousels and content that updates by itself, such as a news feed or live prices, fall under the same criterion, with their own topics.
Fixing this with an AI coding assistant? Get this guide as Markdown
Verify the fix
5 checks.
Test with: Keyboard, Mouse, Reduced motion, Zoom, Screen reader
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the bar, its messages or its library change.
Limits
This is a starting pattern, not a guarantee for every application. It covers movement only: flashing, more than three times in any one second, is a separate check under 2.3.1, made with a flash analysis tool rather than by eye. Whether the movement is essential, and whether the page is calm enough once it is stopped, still needs a person to judge.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
References
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.