Build Systems/Rendering
Respecting prefers-reduced-motion, with a sandbox
The two-line media query, the resting-state rule that matters more, and a live example you can toggle yourself.
Most reduced-motion implementations stop at disabling transitions. The harder half is making sure the *resting* state is the visible one — because a reveal that starts at opacity: 0 and never animates is a blank page, not a calm one.
The rule that actually matters
Every animated element must be readable with no JavaScript and no animation. Test it by disabling JS entirely: if content disappears, the animation is load-bearing and needs inverting.
Try it
Toggle the checkbox to simulate the media query. Notice the second card stays readable throughout — that is the whole trick.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="/styles.css" />
</head>
<body>
<label class="toggle">
<input type="checkbox" id="reduce" />
Simulate prefers-reduced-motion
</label>
<div class="cards">
<article class="card fragile">
<h2>Fragile</h2>
<p>Authored hidden. With motion off, this never appears.</p>
</article>
<article class="card robust">
<h2>Robust</h2>
<p>Authored visible. Motion is an enhancement, not a requirement.</p>
</article>
</div>
<script src="/main.js"></script>
</body>
</html>The same idea in React
Framer Motion's useReducedMotion returns the user's preference. The component below renders a plain element when motion is off — never a hidden one waiting for an animation that will not run.
import { m, LazyMotion, domAnimation, useReducedMotion } from "framer-motion";
function Reveal({ children }) {
const reduced = useReducedMotion();
// The resting state is the visible one. With motion off we render a plain
// div — not a hidden one that happens not to animate.
if (reduced) return <div className="card">{children}</div>;
return (
<m.div
className="card"
initial={{ opacity: 0, y: 16 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
>
{children}
</m.div>
);
}
export default function App() {
return (
<LazyMotion features={domAnimation} strict>
<main>
<h1>Reveal</h1>
<Reveal>
<p>
Turn on "Reduce motion" in your OS settings and reload — this stays
readable.
</p>
</Reveal>
</main>
</LazyMotion>
);
}// related
From the rest of the site.
Design Systems That Survive Contact With Content
Most design systems break the first time a real editor uses them. Here is how to build tokens and components that hold.
