prefers-reduced-motionとは何か
prefers-reduced-motion は、OSやブラウザの設定で「動きを減らす」を有効にしているユーザーを検知できるCSSメディアクエリ兼JavaScriptのマッチメディア機能です。macOSの「視差効果を減らす」、Windowsの「アニメーション効果」オフ、iOS/Androidの「モーションを減らす」など、主要なOSにはすべて同等の設定が用意されています。
サイト側でこの設定を検知し、reduce が指定されている場合はアニメーションを止めたり大幅に弱めたりするのが、動くWebパーツを作るうえでの必須マナーです。派手なパララックスやスクロール演出は、Awwwards的な見栄えを作る一方で、一部のユーザーには「めまい」「吐き気」「頭痛」といった実害を与えることがあります。
なぜ「動きを減らす」設定が必要なのか
原因の多くは前庭障害(へいこう感覚の不調)です。画面上で大きく・速く・不規則に動く要素は、実際には体が動いていないのに「動いている」という視覚情報を脳に送り込みます。この視覚情報と、内耳や体からの「動いていない」という情報のズレが、乗り物酔いに似た症状を引き起こします。
これは一部の特殊な人だけの問題ではありません。前庭機能に何らかの不調を抱える人は決して少なくなく、加齢によっても症状が出やすくなります。「動きを減らす」対応は、特別なアクセシビリティ対応ではなく、標準的な品質基準として扱うべきものです。
実装方法:CSSでの基本パターン
もっとも基本的な書き方は次の形です。
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
}
ただし、この「全部潰す」書き方は事故の元でもあります。アニメーションで初めて要素が opacity:1 になる設計だと、アニメーションを止めた瞬間に要素が永遠に見えなくなる、というバグが典型的に起こります。実務では、要素ごとに「止めたときの最終状態」を明示的に指定するほうが安全です。
.card {
opacity: 0;
transform: translateY(24px);
transition: opacity .6s ease, transform .6s ease;
}
.card.in {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.card {
transition: opacity .2s linear;
transform: none;
}
}
上のデモのような「高さ300vh以上を使ったスクロール連動演出」は特に注意が必要です。単にアニメーションを止めるだけでなく、スクロール量そのものを削るために height を畳んだり、position: sticky を解除したりする必要があります。動きだけを止めて高さはそのままにすると、ユーザーは「やたら長いのに何も起きないページ」を延々スクロールさせられることになり、体験としてはむしろ悪化します。
JavaScriptでの検知と分岐
CSSだけでなくJS側でも検知して、そもそもエフェクト用の重い処理(パーティクル生成やrequestAnimationFrameループ)自体を起動しないようにするのが理想です。
const reduceMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
if (!reduceMotion) {
startParticleLoop();
} else {
renderStaticState();
}
設定はページ読み込み後に変更される可能性もあるため、matchMedia の change イベントも監視できると理想的ですが、多くの実務案件では初回判定だけで十分実用に耐えます。
カーソル追従・自動デモ演出での注意点
[demo:cursor-trail-line] のようなカーソル追従演出は、視覚的な見せ場になりやすい反面、常時動き続けるタイプの演出です。prefers-reduced-motion: reduce の環境では、追従の遅延(イージング)を切って瞬時に位置を合わせる、あるいは追従自体をオフにして静的な表示にとどめる、といった対応が推奨されます。
「放置していても動きが見える自動デモ」を実装している部品も同様です。reduce環境では自動デモのループを止め、初期状態やワンショットの変化だけを見せるようにすると、演出の意図を保ったまま負担を減らせます。
よくある失敗例
- アニメーションのdurationだけ0にして、transformの最終値を反映し忘れ、要素が中途半端な位置で止まる
overflow: hiddenを使った演出で、reduce時にscrollのための余白(高さ)を畳み忘れる- カルーセルやスライダーの自動再生を止めずに、動きの「速さ」だけを落としてお茶を濁す
- CSSのメディアクエリだけ対応し、JSで動かしているcanvasやWebGLの演出を見落とす
アクセシビリティ観点と訴訟リスク
prefers-reduced-motion への対応は、WCAGの達成基準「2.3.3 Animation from Interactions」に関連する項目です。日本国内でも改正障害者差別解消法の施行以降、民間事業者にも合理的配慮の提供が求められるようになり、Webアクセシビリティは「努力目標」から「対応すべき項目」へと重みを増しています。
海外、特に米国ではADA(障害を持つアメリカ人法)を根拠にWebアクセシビリティ不備を理由とした訴訟が数多く提起されており、その対象には過度なモーション演出も含まれます。グローバル向けサイトを持つ場合、この観点は無視できません。法的リスクを抜きにしても、「動きを止められる設計」は低スペック端末での省電力・省負荷にもつながり、ビジネス上のメリットも大きい対応です。
まとめ:実装前のチェックリスト
1. すべてのアニメーション・トランジションにreduce時の最終状態を用意したか 2. スクロール連動演出は高さそのものを畳めているか 3. JSのcanvas/rAFループはreduce時に起動を止めているか、または大幅に負荷を下げているか 4. 自動再生・自動デモはreduce時にループを止めているか 5. reduce環境でも情報の到達(ボタンの意味、状態変化)が損なわれていないか
派手な演出をあきらめる必要はありません。「見せ場」と「安全に見られる状態」を両立させることこそが、これからの動くWebパーツに求められる品質基準です。