All Topics
Visual Considerations
Reducing Motion

Reducing Motion

For many people, motion on a screen can make them sick (opens in a new tab), cause seizures, significant distractability, and more. Fortunately, we have a feature in modern computing systems and browsers where we can make animation and transitions safer and more inclusive!

Reduced Motion was introduced a few years ago as a prefers-reduced-motion (opens in a new tab) CSS Media Query and platform setting. It is supported (opens in a new tab) on Mac and iOS, Windows, and Android. With the ability to add a custom toggle to turn motion on or off, that means you can safely reduce motion pretty much anywhere.

Turning on Reduced Motion

On the MacOS System Preferences under Accessibility > Display, there is a toggle for "Reduce Motion". Turning this on or off will impact how CSS Media Queries and related JavaScript matchMedia functions in web browsers.

MacOS System Preferences for Display
MacOS Settings for Reduced Motion

Using safe defaults

When you write your code for animation/transitions that will need Reduced Motion, you can go about it in a couple of ways:

  1. Non-animated by default, only moving if the setting exists and is unchecked (leveraging prefers-reduced-motion: no-preference)
@media (prefers-reduced-motion: no-preference) {
    .mask {
        /* do animation stuff */
    }
}
  1. Animated by default, stopping movement if the setting exists and is checked (using prefers-reduced-motion: reduce)
@media (prefers-reduced-motion: reduce) {
    .mask {
        /* turn animations off */
        animation: none;
        transition: none;
    }
}

It’s a slight difference. Only the first option will contribute to safe animation by default, no matter whether prefers-reduced-motion is supported on the user’s device.

Example of the CSS media query

Here is an example of how to respond to reduced motion with CSS:

Example of the JavaScript matchMedia query

JavaScript also includes a function for matching the prefers-reduced-motion media query. It is useful for times when your animations are created with JavaScript, video backgrounds, etc.

  const motionQuery = matchMedia('(prefers-reduced-motion: no-preference)');
  let userPrefersMotion = true;
 
  function handleReduceMotionChanged() {
    if (motionQuery.matches) {
      /* adjust 'transition' or 'animation' properties */
      userPrefersMotion = true;
    } else {
      /* standard motion */
      userPrefersMotion = false;
    }
  }
  motionQuery.addEventListener('change', handleReduceMotionChanged);
  
  handleReduceMotionChanged(); // fire once on load

And here is an example using JavaScript matchMedia: