react-reduce-motion
v2.0.2
Published
A cross platform react hook that indicates whether a user's OS is configured to "Reduce motion" for accessibility purposes
Downloads
1,806
Maintainers
Readme
React Reduce Motion ➰
Installation and Usage
❗ React Reduce Motion requires react ^16.8.0 or for native, requires react-native ^0.60.
yarn add react-reduce-motion
React Reduce Motion provides a react hook that exposes the "Reduce Motion" preference of a user's operating system to your componets.
import { useReduceMotion } from 'react-reduce-motion';
Why?
Building animations in React is fun! Especially if you're using a library like react-spring. I recently had some fun messing around with react-spring and learned that animations are not fun for everyone.
Vestibular dysfunction, a balance disorder of the inner ear, is surprisingly common among US adults. A study from the early 2000's found that approximately 69 million Americans had vestibular dysfunction which results in vertigo, nausea, migraines and hearing loss. Many people affected by vestibular dysfunction will choose to set the "Reduce motion" setting in their OS. In macOS it's found in the accessibility settings.
If you're including animations in your app, consider optionally reducing their intensity so that everyone can enjoy your app. There are a couple ways you can do this with React Reduce Motion.
- If you're using
react-spring
, disable animations entirely using a global:
import { Globals } from 'react-spring'
import { useReduceMotion } from 'react-reduce-motion';
const MyApp = () => {
const prefersReducedMotion = useReduceMotion()
React.useEffect(() => {
Globals.assign({
skipAnimation: prefersReducedMotion,
})
}, [prefersReducedMotion])
return ...
}
- Reduce the animation intensity using a heuristic of your choosing:
import { useReduceMotion } from 'react-reduce-motion';
function ParallaxAnimatedButton({ rotation = 10, scale = 1.2 }) {
const buttonRef = React.useRef();
const reduceMotion = useReduceMotion();
const defaultTransform = [0, 0, 1]
// This is where we choose the animation intensity depending on user preference.
const actualRotation = reduceMotion ? rotation / 3 : rotation;
const actualScale = reduceMotion ? 1.01 : scale;
const [props, set] = useSpring(() => ({
xys: defaultTransform,
config: { mass: 7, tension: 500, friction: 40 }
}));
return (
<animated.button
ref={buttonRef}
className="springy-button"
onMouseMove={({ clientX, clientY }) =>
set({ xys: calc(actualRotation, actualScale, clientX, clientY, buttonRef.current) })
}
onMouseLeave={() => set({ xys: defaultTransform })}
style={{
transform: props.xys.to(transform),
}}
>
Hover over me!
</animated.button>
);
}
Before:
After:
const actualRotation = reduceMotion ? rotation / 3 : rotation;
The above snippet is where the heuristic is applied. Depending on what you're animating, you need to make your own decision. See the Resources section below as your guide.
Native
To use React Reduce Motion with React Native, import the native
build use the hook as demonstrated above.
❗ The native react hook provided by React Reduce Motion requires react-native ^0.60.
import { useReduceMotion } from 'react-reduce-motion/native';
Implementation
The web version of this package is based on prefers-reduced-motion
from Media Queries Level 5. See browser support here.
The native version depends on React Native's AccessibilityInfo API which provides a cross platform isReduceMotionEnabled
function. This was introduced in React Native v0.60
.
Inspiration
Writing a blog post about my experience learning react-spring
helped me realize the need for a package that promotes building accessible animations. Read it here and you'll learn how I implemented it. A conversation with Paul, the creator of react-spring, spurred me to contribute this work.
Resources
WCAG 2.1 - Guideline 2.3 Seizures and Physical Reactions
Do not design content in a way that is known to cause seizures or physical reactions. reference
Motion animation triggered by interaction can be disabled, unless the animation is essential [emphasis added] to the functionality or the information being conveyed. reference