Using the reduced motion media query in a project
Tags: css, a11y, webdev
Published: 2023-07-24 13:14:31

The CSS media query `prefers-reduced-motion` is a rule that checks the user's accessibility setting for "reduced motion" in their system preferences. It is not browser, website or session dependent but a setting on the user's computer itself. This media query allows us as developers to update any styles based on the user's preference for animation. 

The intent of this media query is to create a comfortable experience for all users. Animations can cause discomfort and even pain for neurodivergent users which can include people with vestibular disorders and users who are prone to inattention due to ADHD, bipolar disorder, depression or anxiety disorders. Other users may wish to turn on "reduced motion" to minimize distractions or reduce cognitive load. 

The problem is that not all sites accommodate the user's wishes and stop animations if they have selected "reduced motion".

When a user chooses "reduced motion" it does not necessarily mean that they wish to have no motion at all. Some animations are extremely helpful for the user experience in providing visual feedback: a loading spinner that doesn't spin can make the user think the site is frozen, a button changing scale as you click it can emphasize that it has been clicked. Reducing motion is most beneficial when dealing with big parallax effects, scroll hijacking and animations that cover lots of screen space as these are most likely to cause issues for motion-sensitive users. 

A developer's initial instinct to using the `prefers-reduced-motion` media query might be to stop animations on an individual selector basis:
```css
  @media screen and (prefers-reduced-motion) {
    animation: none;
    transition: none;
  }
```
This will likely cause issues because the animations can get stuck at their initial value (ie. opacity: 0 and the position is off screen).

We want a more global solution that will make it easier to develop for users who want less motion. We also need for the animations to play so that the elements end up at their desired end point, while not noticing the in-between states of the animation. We can use the animation and transition `duration` property to force the animations to run at a speed so fast that it is imperceivable. 

In the root level of our CSS, we call the reduced-motion media query and target a specific class that will 'turn off' the animations for those elements.

A more global and adaptable solution: 
```css
@media only screen and (prefers-reduced-motion) {
  .reduce-motion,
  .reduce-motion::before,
  .reduce-motion::after {
    animation-delay: 0s !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important; 
    transition-duration: .0001ms !important;
    transition-delay: 0s !important;
  }
}
```
As we are developing, we can add the class `reduce-motion` to any elements that we think are not necessary to the user experience or could cause discomfort to the motion-sensitive users. 

While we try to use the `!important` property as little as possible, it is a valuable use of it here since the point is to be a global override of any animation and transition properties further down the style-sheet. 

This isn't necessarily a perfect solution but it is important to have these conversations about how different people experience the web. In order to build more inclusive sites, we need to listen to issues people have and address them with any tools that we have available to us. 

Sources that helped inform this article:
- https://css-tricks.com/revisiting-prefers-reduced-motion/
- https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/
- https://alistapart.com/article/designing-for-cognitive-differences/