On this page
Motion Accessibility and Performance: prefers-reduced-motion, will-change and Smooth 60fps Animations
Why motion accessibility matters
Motion accessibility means making sure animation helps users instead of harming them. Large movement, parallax, zooming, spinning and constant looping can trigger dizziness, nausea, migraines or distraction for people with vestibular disorders, epilepsy, ADHD or cognitive differences. Operating systems provide a setting such as Reduce Motion, and the CSS media feature prefers-reduced-motion lets your site respond to it.
Focus keyword: prefers-reduced-motion. Related trending keywords: reduced motion CSS, accessible animations, WCAG animation guidelines, CSS animation performance, will-change, compositor-only animations, Interaction to Next Paint (INP), Core Web Vitals animation, 60fps animation.
The prefers-reduced-motion media query
@media (prefers-reduced-motion: reduce): the user asked the system to minimize non-essential motion.@media (prefers-reduced-motion: no-preference): no request has been made.
Reduce does not always mean remove. Replace large movement (sliding, zooming, spinning, parallax, bouncing) with gentle alternatives such as a short opacity fade or an instant state change. Keep essential motion that explains a change, but make it smaller and calmer.
Two implementation strategies
- Opt-out (reduce first): write animations normally, then inside
@media (prefers-reduced-motion: reduce)disable or simplify them. Quick to add to an existing project. - Opt-in (no-preference first): write motion only inside
@media (prefers-reduced-motion: no-preference). This is safer, because users with the preference (and browsers that do not report it) get the calm version by default.
A common global safety net sets animation and transition durations to near zero and stops scroll-behavior smoothing. It is a good last resort, but design intentional reduced versions for important components.
Reading the preference in JavaScript
Use window.matchMedia('(prefers-reduced-motion: reduce)'). Listen for changes with addEventListener('change', ...) because users can switch the setting while the page is open. Apply it to JavaScript animation libraries, autoplaying carousels, canvas and WebGL effects, video backgrounds and View Transitions as well.
WCAG rules you should know
- 2.2.2 Pause, Stop, Hide (Level A): any moving, blinking or auto-updating content that starts automatically, lasts more than 5 seconds and appears alongside other content needs a mechanism to pause, stop or hide it.
- 2.3.1 Three Flashes or Below Threshold (Level A): nothing should flash more than three times per second.
- 2.3.3 Animation from Interactions (Level AAA): motion triggered by interaction can be disabled unless essential.
Also avoid motion that blocks reading, and never hide critical information behind an animation that only runs once.
CSS animation performance basics
Browsers render in stages: style, layout, paint and composite. The cheapest animations only touch the composite stage, which can run on the GPU and even off the main thread.
- Cheap (composite only):
transform,opacity. In many browsersfilterandbackdrop-filterare also composited but can be costly on large areas. - Medium (paint):
color,background-color,box-shadow,border-radius. - Expensive (layout):
width,height,margin,padding,top,left,font-size. These can force the page to recalculate positions for many elements.
Replace left with translateX, width with scaleX (when appropriate), and fading with opacity.
will-change, contain and content-visibility
will-change: transformhints that an element is about to animate so the browser can promote it to its own layer. Use it sparingly, add it shortly before an animation and remove it afterward. Too many layers waste memory and can slow the page.contain: layout paint(orcontain: content) limits how far the browser must recalculate when something changes.content-visibility: autoskips rendering of off-screen sections, which frees time for animations that matter.
JavaScript animation tips
- Use
requestAnimationFramefor visual updates, neversetInterval. - Prefer the Web Animations API (
element.animate()) or CSS over manual style changes. - Avoid reading layout values (like
offsetHeight) and writing styles in the same loop, which causes layout thrashing. - Keep main-thread work short so user input stays responsive. Long tasks hurt the Core Web Vitals metric INP.
- Do not use animation on LCP elements in a way that delays their first visible paint.
How to measure
- Chrome DevTools, Performance panel: record, look for long frames, layout and paint cost.
- Rendering tab: enable Paint flashing, Layout Shift Regions and FPS meter.
- Animations panel: slow down and inspect timing.
- Test on a mid-range phone, not only your laptop. Also test with OS Reduce Motion turned on.
Checklist
- Motion has a purpose (feedback, orientation, hierarchy).
- Large or looping motion respects
prefers-reduced-motion. - Autoplaying motion longer than 5 seconds can be paused.
- Only transform and opacity are animated for frequent or large effects.
- No flashing content above the WCAG threshold.
- will-change is used rarely and removed after use.
- Keyboard and screen reader users get the same information without the animation.
Quick summary
Great motion design is fast, purposeful and optional. Use prefers-reduced-motion to adapt to user needs, follow WCAG rules, and keep your animations on the compositor for smooth performance.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
The .slider currently animates the left property forever. Rewrite the keyframes to use transform instead of left, and add a prefers-reduced-motion: reduce rule that stops the animation completely. Bonus: add will-change: transform only while the animation runs.
Press Run to execute.
Show expected output
The square slides back and forth using transform: translateX(260px), and does not animate when the OS Reduce Motion setting is enabled.This is a self-check — compare your result with the expected output above.
Was this page helpful?