Motion can show that an interface changed, but the change must remain understandable without movement. Respect prefers-reduced-motion and give people an immediate, visible state change when animation is removed.
A brief transition with a reduced-motion alternative
HTML and CSS
HTML
<button class="toggle" type="button" aria-pressed="false">Pin item</button>
<script>
const button = document.querySelector("button");
button.addEventListener("click", () => {
button.setAttribute("aria-pressed", button.getAttribute("aria-pressed") !== "true");
});
</script>
CSS
.toggle {
padding: 0.75rem 1rem;
border: 2px solid #164eae;
background: white;
color: #164eae;
}
.toggle[aria-pressed="true"] {
background: #164eae;
color: white;
}
@media (prefers-reduced-motion: no-preference) {
.toggle {
transition:
background-color 150ms ease,
color 150ms ease;
}
}
Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.
The button’s aria-pressed state announces whether it is on. The colors change immediately for reduced-motion users; other users get a short transition. The accessible name remains “Pin item” in both states so the pressed state supplies the on/off distinction.
Transitions and animations
A transition runs when a property’s value changes. An animation uses named keyframes and can run without a user action. Use a transition for a brief state change; use keyframes when you need a defined sequence.
Animating transform or opacity can often avoid repeated layout work, but compositing behavior depends on the browser and surrounding page. Measure the result instead of adding will-change to every element.
Turn off an unnecessary animation
@media (prefers-reduced-motion: no-preference) {
.status-icon { animation: pulse 1.5s ease-in-out infinite; }
}
@keyframes pulse {
50% { opacity: .6; }
}
The baseline is a still icon, so reduced-motion users never start the animation. A textual status should explain what is happening in either mode. An animation that provides essential meaning needs another way to convey that meaning.
Test the preference
Enable reduced motion in the operating system or emulate it in browser developer tools. Reload the document and activate the button with a keyboard. Confirm that the state change still has clear feedback and no unnecessary movement.
reduce means the person has asked to reduce nonessential motion. no-preference means they have not expressed that preference; it does not mean they want every interface to move.
Common mistakes
Do not rely on animationend for essential application state when your reduced-motion rules can remove the animation. Do not use transition: all without checking which properties may change. Large panning, scaling, parallax effects, and persistent motion deserve particular care.
Smooth scrolling is also motion. Apply scroll-behavior inside no-preference if smooth scrolling is useful, and retain immediate scrolling otherwise.
Source
MDN: prefers-reduced-motion explains the media feature and ways to test it.