useReducedMotion
A React hook that detects the user's prefers-reduced-motion OS setting and responds to changes in real time.
Preview
prefers-reduced-motion: no-preference
Hover me — animations enabled
Toggle "Reduce motion" in your OS accessibility settings to see the change in real time.
Installation
npx shadcn@latest add @shadszn/use-reduced-motionSource
"use client"
import { useEffect, useState } from "react"
export function useReducedMotion(): boolean {
const [prefersReduced, setPrefersReduced] = useState(false)
useEffect(() => {
const mql = window.matchMedia("(prefers-reduced-motion: reduce)")
setPrefersReduced(mql.matches)
const handler = (e: MediaQueryListEvent) => setPrefersReduced(e.matches)
mql.addEventListener("change", handler)
return () => mql.removeEventListener("change", handler)
}, [])
return prefersReduced
}Usage
"use client"
import { motion } from "framer-motion"
import { useReducedMotion } from "@/hooks/use-reduced-motion"
import { fadeInUp } from "@/lib/motion"
export function AnimatedCard({ children }) {
const prefersReduced = useReducedMotion()
return (
<motion.div
variants={prefersReduced ? undefined : fadeInUp}
initial={prefersReduced ? false : "hidden"}
animate="visible"
>
{children}
</motion.div>
)
}Conditional Transitions
const prefersReduced = useReducedMotion()
// Skip spring animations for users who prefer reduced motion
const transition = prefersReduced
? { duration: 0 }
: { type: "spring", stiffness: 300, damping: 20 }
<motion.div
whileHover={prefersReduced ? undefined : { y: -4 }}
transition={transition}
>
Hover card
</motion.div>Return Value
| Prop | Type | Default | Description |
|---|---|---|---|
| prefersReduced | boolean | false | Returns true when the user has enabled "Reduce motion" in their OS accessibility settings. Defaults to false on the server and updates on mount. |