Accessibility
Animations can have serious usability implications, even inducing motion sickness in some people.
All modern operating systems provide a setting called "Reduced Motion", where people can indicate they prefer less physical motion, either because of personal preference or because they can suffer from motion sickness.
There are already some excellent guides about why and how we should design accessible animations, like those at A List Apart and Smashing Magazine. The main takeaways are that for users with "Reduced Motion" enabled, we should keep educational transitions but be aware of motion sickness.
That means replacing transform animations on large elements with opacity transitions, disabling auto-playing videos, and disabling parallax animations.
Motion for React provides APIs that make it simple to respect these people's preferences. In this guide, we'll learn how to use the reducedMotion
option and useReducedMotion
hook to make our animations accessible.
Automatic
The reducedMotion
option can be set on MotionConfig
to define how you want to adhere to the Reduced Motion setting.
By setting reducedMotion
it to "user"
, all motion
components will automatically disable transform and layout animations, while preserving the animation of other values like opacity
and backgroundColor
.
Framer, the no-code site builder, uses this API and exposes it via a setting in Site Settings > Accessibility
.
Additionally, you can allow a user to override Reduced Motion for just your site by setting reducedMotion to "always"
or "never"
based on their profile.
Manual
While reducedMotion
is a great blanket tool for ensuring accessible animations across your whole site, more bespoke solutions can be created with the useReducedMotion
hook.
This hook returns true
/false
depending on whether your visitor has Reduced Motion enabled.
We can use this boolean to fix some of the common accessibility problems, like the following.
Replace transform
with opacity
When Reduced Motion is enabled on iOS, the operating system still animates between states to help users transition between each context. But instead of the default scale and x/y animations, it fades content in and out.
We can achieve this in Motion by passing different values to animate
based on whether useReducedMotion
returns true
or not.
Disable auto-playing video
useReducedMotion
isn’t only compatible with the Motion. It returns a simple boolean, so you can use it for any purpose, like disabling the autoplay of a background video
element:
Disable parallax
Parallax animations can be very unpleasant for people pre-disposed to motion sickness.
To build parallax, we usually get scrollY
from useViewportScroll
, and create a new MotionValue
via passing that to useTransform
which will update's a motion
component's y
position as the scroll value changes.
To disable this for reduced motion devices, we can conditionally pass this MotionValue
to the animating element.
Conclusion
We've learned to respect people's Reduced Motion setting with Motion for React. The reducedMotion
option makes it simple to implement across a whole site, while useReducedMotion
can help us create bespoke accessibility strategies with any React API.