Motion slop examples: 7 patterns from 196 AI sites
Motion slop shows up as a small number of recurring, checkable patterns — not as endless variety. In the State of Motion study we statically scanned 196 AI-generated production apps; the median app carried 17 distinct motion root causes, and only 6 of 196 (3.1%) came back clean. Underneath those root causes sit the same few defect shapes, again and again. This page catalogs the seven we see most, each with the concrete CSS or behavior that identifies it, the reason it hurts users, and the fix. If you want the definition first, read What is motion slop?; if you want a repo-level triage workflow, read How to detect and fix motion slop.
To be clear about intent: this is a defect catalog with fixes, not an inspiration gallery — every example below is a pattern to remove, not one to copy.
1. The unguarded animation
An unguarded animation is any CSS animation or transition that runs regardless of the user's prefers-reduced-motion setting. It is the ambient defect: in the study, 96.9% of the 196 apps shipped at least one — which we report as a best-practice gap in the lane of WCAG 2.3.3 (Animation from Interactions, Level AAA), not as a Level A/AA failure.
How to spot it. Search the codebase for prefers-reduced-motion. If nothing comes back, every animation and transition declaration in the project is unguarded. If there are hits, the findings are the declarations sitting outside those guarded blocks.
Why it hurts. People with vestibular disorders turn on the OS toggle because motion can cause them dizziness and nausea. An unguarded animation ignores that request — the user asked, the page didn't listen.
/* before: runs for everyone, always */
.card { transition: transform .2s ease; }
/* after: opt-in only */
@media (prefers-reduced-motion: no-preference) {
.card { transition: transform .2s ease; }
}
Fix rule: non-essential motion is opt-in, never default. The full pattern, including the JavaScript guard, is in our prefers-reduced-motion guide.
2. The infinite loop with no pause path
An infinite loop with no pause path is motion that starts automatically, repeats forever, and offers no way to pause, stop, or hide it — the pattern WCAG 2.2.2 (Pause, Stop, Hide, Level A) exists to prevent. This is the hard failure in the data: 66.3% of the 196 apps ran at least one.
How to spot it. In CSS, the infinite keyword in an animation shorthand or animation-iteration-count. In JavaScript, iterations: Infinity, repeat: -1, or loop: true. Then check for what's missing: no pause control, no bounded end, no state that removes it.
Why it hurts. Motion that never rests competes with the content for attention for as long as the page is open. For people with attention or cognitive disabilities, reading next to a permanent pulse is measurably harder; for everyone else it's low-grade noise.
/* before: pulses forever */
.badge { animation: pulse 0.8s infinite; }
/* after: draws the eye, then rests */
@media (prefers-reduced-motion: no-preference) {
.badge { animation: pulse 0.8s ease-in-out 3; }
}
Fix rule: bound the iteration count, wire animation-play-state: paused to a visible control, or tie the loop to a real pending state and remove it the moment the state resolves. A loop that is essential and under five seconds satisfies 2.2.2; "it's just a small spinner" does not.
3. The autoplay carousel
An autoplay carousel is a slideshow that advances on its own timer, without user input and without a pause control. When it runs longer than five seconds alongside other content — which a looping carousel always does — it sits in the same WCAG 2.2.2 (Level A) lane as the infinite loop.
How to spot it. A setInterval (or library equivalent) advancing a transform on a track element; testimonial or logo sliders on generated landing pages; pagination dots that move on their own.
Why it hurts. It takes text away while people are reading it. Keyboard and screen-reader users have it worst: the slide they were interacting with leaves mid-task.
Fix rule: make carousels user-advanced by default. If autoplay is a genuine requirement, add an explicit, visible pause/stop control — pausing on hover alone is not a control — and stop after the last slide instead of looping.
4. Scroll hijacking
Scroll hijacking is scripted scrolling that replaces the browser's native scroll — the page, not the user, decides how far and how fast the viewport moves. Interaction-triggered motion like this is exactly the scope of WCAG 2.3.3 (Level AAA), which we treat as the best-practice lane, not a failure to certify against.
How to spot it. wheel or touchmove listeners that call preventDefault() and re-implement scrolling; full-viewport "section snap" effects animated over hundreds of milliseconds; parallax layers moving at rates the content doesn't.
Why it hurts. Scrolling is the input users calibrate most precisely, and hijacking takes that calibration away. Large, sweeping viewport motion tied to a small hand movement is also a classic vestibular trigger.
Fix rule: keep native scrolling. If you want section alignment, CSS scroll-snap positions the viewport without taking over the gesture. Any scroll-linked effect that remains should be small, and disabled entirely under prefers-reduced-motion: reduce.
5. transition: all
transition: all tells the browser to animate every animatable property that ever changes on an element. It is a performance and maintainability defect rather than a WCAG item — but every unguarded transition it creates lands in pattern 1.
How to spot it. Search the stylesheets for transition: all (and shorthands whose property list is all). Generators emit it as a one-line "polish" rule on buttons, cards, and inputs.
Why it hurts. Properties animate that nobody designed to move: a layout shift glides instead of settling, a color-scheme change smears. And the rule is open-ended — any expensive property someone adds to that element later inherits an animation nobody decided on. It also makes a motion audit unreliable, because the set of things that can move is unbounded.
/* before: animates anything that ever changes */
.button { transition: all .3s; }
/* after: animates exactly what was designed to move */
.button { transition: transform .2s ease, opacity .2s ease; }
Fix rule: name the properties. If you can't list what should animate, that's the design question to answer first.
6. The layout-property animation
A layout-property animation moves or resizes an element by animating reflow-forcing properties — top, left, width, height, margin — instead of transform. This is a performance defect, not a WCAG criterion: the browser must recompute layout on every frame, which shows up as jank on mid-range devices and pressure on Core Web Vitals. The study's open dataset counts these per app as risky-property occurrences.
How to spot it. @keyframes bodies or transitions that touch those properties. The classic specimen is a menu sliding in via left: -320px → 0, or a card growing via width.
Why it hurts. Every frame forces a reflow, and the cost scales with how much of the page depends on that element's geometry. The same visual is available for free on the compositor path.
/* before: reflow on every frame */
.menu { left: -320px; transition: left .3s; }
.menu.open { left: 0; }
/* after: compositor path, same visual */
.menu { transform: translateX(-320px); transition: transform .3s; }
.menu.open { transform: none; }
Fix rule: re-express movement and scaling in transform (and fades in opacity). Paint-only properties like box-shadow don't force reflow but still repaint off the compositor — only transform and opacity stay on the fast path.
7. The overlong entrance sequence
An overlong entrance sequence keeps content invisible or in motion for a noticeable time after the page is ready, usually via staggered fade-ins. A one-shot entrance under five seconds doesn't fail WCAG 2.2.2 — the honest objections are usability and the missing guard, and unguarded it also plays for users who asked for reduced motion.
How to spot it. Content styled opacity: 0 by default, revealed by animation-delay chains; hero copy fading in line by line; a page that is blank until a script runs.
Why it hurts. Everyone waits, on every visit, for content that was already there. And when the reveal depends on JavaScript, a failed script load means the content never appears at all.
Fix rule: ship content visible by default and treat the entrance as an enhancement layered on top. Keep the total choreography short, run it once, and put it behind the prefers-reduced-motion: no-preference guard like everything else.
Where do these patterns come from?
Every pattern above is drawn from the State of Motion study, a static scan of 196 AI-generated production apps. The scan reads each app's linked CSS and inline styles and counts, per app, unguarded motion, risky layout properties, and infinite loops without a pause path. The headline numbers: 66.3% of apps ran at least one infinite animation with no way to pause it (a WCAG 2.2.2 Level A failure), 96.9% shipped at least one motion with no reduced-motion guard (a best-practice gap, not an A/AA failure), and 6 of 196 — 3.1% — came back clean. Every figure is a static lower bound: runtime JavaScript motion isn't in these counts. Method, cohort tables, and caveats are in the full study; the anonymized per-app dataset is published as CC-BY CSV.
How do you keep these patterns out at the source?
Detection finds the patterns; construction prevents them. The triage in detect and fix motion slop catches most of this catalog in minutes, and the free motion check runs the CSS half of that pass statically against WCAG 2.2.2 and 2.3.3 — as detection, not a conformance claim. The structural answer is to assemble animation from primitives that carry the guard, the bounded loop, and the property budget by construction, so the seven patterns above can't be emitted in the first place — that's the layer MotionSpec builds, documented in the MCP docs.
Paste any URL into the free motion check and see which of these patterns a static scan finds — every finding with the fix.
Run the free motion checkFAQ
What is the most common motion slop pattern?
Unguarded motion. In the scan of 196 AI-generated production apps, 96.9% shipped at least one animation or transition with no prefers-reduced-motion guard — a best-practice gap, not a Level A/AA failure. The most common hard failure was the infinite loop with no pause path: 66.3% of apps, a WCAG 2.2.2 Level A failure.
Are all seven patterns WCAG failures?
No. Infinite loops and autoplay carousels fail WCAG 2.2.2 (Pause, Stop, Hide, Level A) when motion starts automatically, runs longer than five seconds alongside other content, and has no pause path. Missing reduced-motion guards map to WCAG 2.3.3, a Level AAA criterion scoped to interaction-triggered motion — a best-practice gap, not an A/AA failure. transition: all and layout-property animation are performance defects, not WCAG items.
How do I check my own site for these patterns?
Manually: turn on your OS reduced-motion setting, reload, and watch what still moves; then search the stylesheet for infinite, transition: all, and layout properties inside @keyframes. The free motion check automates the CSS half against WCAG 2.2.2 and 2.3.3 — it reports detection, not conformance.
Where do the numbers on this page come from?
From the State of Motion study, a static scan of 196 AI-generated production apps. The median app carried 17 distinct motion root causes; 6 of 196 (3.1%) came back clean. The anonymized per-app dataset is published under CC-BY-4.0.
Generating web UI at scale? See the Design Partner Program.
MotionSpec verifies and compiles UI animation for AI-generated web apps — it does not generate AI video.