Motion
Reduced motion
Motion can trigger discomfort for people with vestibular motion disorders. Animations such as scaling or panning large objects can be vestibular motion triggers. According to vestibular.org, as many as 35% of adults aged 40 years or older in the United States have experienced some form of vestibular dysfunction.
As such, all animations which could be vestibular triggers should respect the
prefers-reduced-motion
user preference. You can find links to articles and documentation around
reduced motion in the resources section if you'd like to
learn more about this.
Implementation
How you handle prefers-reduced-motion
depends on the technology you're using to implement motion.
There are a couple of examples below, but you can find more information in
the resources section.
CSS animations
When using CSS transitions or animations, you can use the prefers-reduced-motion
media query to
opt in to animations. For example:
.fancy-box { width: 100px; height: 100px; transform: scale(1); } .fancy-box:hover { transform: scale(1.2); } @media (prefers-reduced-motion: no-preference) { .fancy-box { transition: transform 300ms; } }
no-preference
is the default value for the prefers-reduced-motion
media query. This means that
if the user hasn't set a preference (or has explicitly allowed motion), the transition will be
enabled.
Framer Motion animations
Framer Motion exposes a useReducedMotion
hook that you can use to disable animations when
prefers-reduced-motion
is set. For example:
export function Sidebar({isOpen}: {isOpen: boolean}) { const shouldReduceMotion = useReducedMotion() const closedX = shouldReduceMotion ? 0 : '-100%' return ( <motion.div animate={{ opacity: isOpen ? 1 : 0, x: isOpen ? 0 : closedX, }} /> ) }
Types of motion to avoid when prefers-reduced-motion
is set
Scale, zoom, spinning or positional animations can be particularly problematic for users with vestibular disorders. These should be avoided or replaced with opacity fades.
We should also avoid flickering or blinking animations. These can be distracting, and in some cases can trigger epileptic episodes.
Colour transitions and opacity fades tend not to be vestibular triggers, so something like
transitioning the background colour of an element on hover is generally safe. Furthermore, opacity
fades are often a good replacement for animations that are vestibular triggers when
prefers-reduced-motion
is set. For example, when opening a
Drawer component, we fade the Drawer in and out rather
than sliding it in from the side of the screen. This ensures users still get the benefits of motion
when opening a Drawer, but in a way that is less likely to trigger vestibular discomfort.
Testing reduced motion
You can test reduced motion animations either by emulating the prefers-reduced-motion
media query
in your browser's developer tools, or by setting it at the operating system level. You can learn
more about how to emulate this in your browser by following the guide in the
Google Chrome documentation.