Auto-playing carousels, tickers, or looping animations that run without pause controls cause concentration difficulties for users with attention disorders and can trigger seizures in photosensitive users if they flash. WCAG 2.2 SC 2.2.2 (Pause, Stop, Hide) is a Level A requirement for any animation or auto-updating content that lasts more than 5 seconds. Carousels are the most common violator — they advance silently and provide no control.
Low because the violation is bounded to components with animations longer than 5 seconds, but for affected users — particularly those with vestibular disorders or ADHD — the inability to pause is a real usability blocker per WCAG 2.2 SC 2.2.2.
Add pause/play controls to any animation that runs longer than 5 seconds. Respect the user's prefers-reduced-motion preference to disable motion entirely for users who have set it.
export function AutoCarousel({ slides }: { slides: React.ReactNode[] }) {
const [isPlaying, setIsPlaying] = useState(true)
const [current, setCurrent] = useState(0)
useEffect(() => {
if (!isPlaying) return
const timer = setInterval(() => setCurrent(i => (i + 1) % slides.length), 4000)
return () => clearInterval(timer)
}, [isPlaying, slides.length])
return (
<div>
<button
onClick={() => setIsPlaying(p => !p)}
aria-label={isPlaying ? 'Pause carousel' : 'Play carousel'}
>
{isPlaying ? <PauseIcon /> : <PlayIcon />}
</button>
{slides[current]}
</div>
)
}
Also add @media (prefers-reduced-motion: reduce) { animation: none; } to your global CSS for all decorative motion.
ID: accessibility-wcag.understandable.animation-control
Severity: low
What to look for: Enumerate every relevant item. Look for animations lasting longer than 5 seconds: carousels, auto-rotating banners, loading spinners, animated GIFs, or real-time data updates. Check for pause/stop controls or a way to disable motion.
Pass criteria: At least 1 of the following conditions is met. Animations longer than 5 seconds have pause, stop, or hide controls. Users can disable animations via browser settings or app preference.
Fail criteria: Auto-playing animations have no pause control.
Skip (N/A) when: The project has no animations lasting longer than 5 seconds.
Detail on fail: Example: "Homepage carousel auto-rotates with no pause button. Loading animation spins indefinitely without user control"
Remediation: Add pause/play controls to animations:
export function Carousel({ autoPlay = true }) {
const [isPlaying, setIsPlaying] = useState(autoPlay)
return (
<div>
<button onClick={() => setIsPlaying(!isPlaying)}>
{isPlaying ? 'Pause' : 'Play'}
</button>
{/* Carousel content that respects isPlaying */}
</div>
)
}