Motion
Back to framer.com
DocumentationGuides
Accessibility
Motion
Back to framer.com
Design and publish your first free site today.
Getting started
  • Introduction
  • Examples
Animation
  • Overview
  • Layout
  • Gestures
  • Scroll
  • Transition
Components
  • motion
  • AnimatePresence
  • LayoutGroup
  • LazyMotion
  • MotionConfig
  • Reorder
Motion values
  • Overview
  • useMotionValueEvent
  • useMotionTemplate
  • useScroll
  • useSpring
  • useTime
  • useTransform
  • useVelocity
  • useWillChange
Utilities
  • animate
  • transform
  • useAnimationControls
  • useAnimationFrame
  • useDragControls
  • useInView
  • useReducedMotion
3D
  • Introduction
  • LayoutCamera
  • LayoutOrthographicCamera
  • MotionCanvas
Guides
  • Accessibility
  • Reduce bundle size
  • Upgrade guides
Community
  • GitHub
  • Discord

Accessibility

How to design accessible animations with Framer Motion.

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. So that means replacing transform animations on large elements with opacity transitions, disabling auto-playing videos, and disabling parallax animations.

Framer Motion 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.

#reducedMotion

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.

import { MotionConfig } from "framer-motion"
export function App({ children }) {
return (
<MotionConfig reducedMotion="user">
{children}
</MotionConfig>
)
}

In Framer, you can set this by going to Site Settings > Accessibility and checking the "Disable transform and layout animations if user prefers reduced motion" checkbox.

Additionally, you can allow a user to override Reduced Motion for just your site by setting reducedMotion to "always" or "never".

#useReducedMotion

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.

import { useReducedMotion } from "framer-motion"
// In your component
const shouldReduceMotion = useReducedMotion()

We can use this boolean to fix some of the common accessibility problems identified at the start of this guide.

#Replace transitions 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 Framer Motion by passing different values to animate based on whether useReducedMotion returns true or not.

function Sidebar({ isOpen }) {
const shouldReduceMotion = useReducedMotion()
let animate
if (isOpen) {
animate = shouldReduceMotion ? { opacity: 1 } : { x: 0 }
} else {
animate = shouldReduceMotion
? { opacity: 0 }
: { x: "-100%" }
}
return <motion.div animate={animate} />
}

#Disable auto-playing videos

useReducedMotion isn’t only compatible with the Framer Motion. It returns a simple boolean, so you can use it for any purpose, like disabling the autoplay of a background video element:

function BackgroundVideo() {
const shouldReduceMotion = useReducedMotion()
return <video autoplay={!shouldReduceMotion} />
}

#Disable parallax animations

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.

function Parallax() {
const shouldReduceMotion = useReducedMotion()
const { scrollY } = useViewportScroll()
const y = useTransform(scrollY, [0, 1], [0, -0.2], {
clamp: false,
})
return (
<motion.div style={{ y: shouldReduceMotion ? 0 : y }} />
)
}

#Conclusion

We've learned to respect people's Reduced Motion setting with Framer Motion. 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.

In the future, we'd like to set reducedMotion="user" by default, so let us know via our Twitter if you think we can improve way it affects animation accessibility.

PreviousMotionCanvasNextReduce bundle size
On this page
  • reducedMotion
  • useReducedMotion
  • Replace transitions with opacity
  • Disable auto-playing videos
  • Disable parallax animations
  • Conclusion

Copyright © 2022 Framer B.V.

  • Security
  • Terms of Service
  • Privacy Statement