Reduce Motion — 前庭障害のあるユーザーの不快感を防ぐためにインターフェースのアニメーションを無効化または削減する、OSとブラウザのアクセシビリティ機能です。iOSではこの設定はSettings > Accessibility > Motion > Reduce Motionにあり、パララックス、画面遷移のアニメーション、アイコンのエフェクトを無効化します。Androidでは同等のオプション“アニメーションを削除”がSettings > Accessibilityにあります。W3C WCAG 2.2によると、過度なアニメーションは前庭障害のある人の15〜35%に吐き気、めまい、片頭痛を引き起こす可能性があります。
重要ポイント
Reduce Motion — OS、ブラウザ、アプリに対してアニメーション、動き、拡大縮小、パララックス効果を最小限にするか完全に無効化するよう指示するシステム設定です。この機能は前庭障害のある人向けに作られており、彼らには動くインターフェース要素が吐き気、めまい、方向感覚の喪失、片頭痛を引き起こします。
内耳の前庭系は平衡感覚と空間認識を担います。目が画面上の動きを見る一方で、前庭器官が身体の対応する移動を感じないとき、感覚の衝突が生じます。この衝突は自律神経反応を引き起こします:吐き気、冷や汗、めまいです。Vestibular Disorders Associationによると、40歳以上の約35%の人がインターフェースのモーションエフェクトによる不快感を経験しています。
Reduce Motionと単なるアニメーション無効化の決定的な違いはシステムレベルです。有効にすると、この設定はOSのAPIまたはCSSメディア機能prefers-reduced-motionを通じてすべてのアプリとウェブサイトに伝わります。開発者はユーザーがアニメーションを望むか推測する必要がありません — OSが教えてくれます。これはprogressive enhancement(段階的拡張)のアプローチの一部です:アニメーションは強化であり、必須要素ではありません。
Reduce Motionはパララックス効果(デバイスを傾けたときの背景のずれ)、画面遷移のアニメーション(push、slide、fade)、タップ時のアイコンの拡大、メッセージのエフェクト(SMSの吹き出し)、読み込みアニメーション(スピナー、スケルトン、プログレスバーのアニメーション)、ゲーム内のパララックス、ウェブのパララックススクロール効果に影響します。静止画像と動画は影響を受けません。
| アニメーションの種類 | iOS Reduce Motion | Android Remove Animation | CSS prefers-reduced-motion |
|---|---|---|---|
| 壁紙のパララックス | 無効化 | 無効化 | N/A |
| 画面遷移 | フェードに置き換え | 無効化 | CSS transitions |
| アイコンのアニメーション | 無効化 | 影響なし | CSS animations |
| 読み込みスピナー | 影響なし | 無効化 | CSS animations |
| スケルトン画面 | 影響なし | 静止に置き換え | CSS animations |
Reduce Motionの主な対象は前庭障害(メニエール病、迷路炎、BPPV)、片頭痛(特に前兆を伴うもの)、動揺病(乗り物酔い)、特定のてんかんの形態を持つ人です。この機能は高齢のユーザーにも有用です — 前庭器官の加齢変化は動きへの感受性を高めます — またADHDのユーザーにも役立ちます。動く要素が読書の妨げになるためです。
iOSではReduce MotionはSettings > Accessibility > Motionにあり、3つのオプションがあります:Reduce Motion(メインのスイッチ)、Auto-Play Message Effects(iMessageのエフェクトの自動再生)、Auto-Play Video Previews(App Storeの動画の自動再生)。Reduce Motionは最も強力です:壁紙のパララックス、アプリを開くアニメーション(ズーム)、画面遷移(pushはcross-fadeに置き換え)、ホーム画面のアイコンのエフェクトを無効化します。
技術的には、iOSはUIKitレベルでUIView animationsとUIViewControllerAnimatedTransitioningを通じてReduce Motionを実装します。設定が有効な場合、duration > 0のUIView.animateは0.01秒に短縮され、UIViewController.transitionDurationは0を返します。パララックスのために、iOSはUIWindowでUIInterpolatingMotionEffectを無効化します。開発者はUIAccessibility.isReduceMotionEnabledで状態を確認できます。
開発者はiOSのアニメーションをReduce Motionに適応できます:複雑な遷移をフェード効果に置き換え、カスタムUIコンポーネントのパララックスを無効化し、アニメーションの時間を短縮します。SwiftUIはreduceMotionが有効なときに特別な.animation(nil)モディファイアを提供します。
import UIKit
class MotionManager {
// Reduce Motionの状態を確認
static var isReduceMotionEnabled: Bool {
return UIAccessibility.isReduceMotionEnabled
}
// Reduce Motionを考慮した安全なアニメーション
static func animate(
duration: TimeInterval,
delay: TimeInterval = 0,
options: UIView.AnimationOptions = [],
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil
) {
let adjustedDuration = isReduceMotionEnabled
? 0.01
: max(duration, 0.01)
UIView.animate(
withDuration: adjustedDuration,
delay: delay,
options: options,
animations: animations,
completion: completion
)
}
}
// SwiftUI — Reduce Motion用のモディファイア
import SwiftUI
struct MotionAwareView: View {
@Environment(\.accessibilityReduceMotion)
private var reduceMotion
@State private var isAnimating = false
var body: some View {
Circle()
.scaleEffect(isAnimating ? 1.2 : 1.0)
.animation(
reduceMotion
? nil
: .easeInOut(duration: 1.0).repeatForever(),
value: isAnimating
)
.onAppear { isAnimating = true }
}
}
// Reduce Motionの変更を購読
NotificationCenter.default.addObserver(
self,
selector: #selector(motionStatusChanged),
name: UIAccessibility.reduceMotionStatusDidChangeNotification,
object: nil
)MotionManagerクラスはisReduceMotionEnabledを確認し、アニメーションの時間を適応させます:Reduce Motionが有効な場合、時間は0.01秒(実質的に瞬間)に短縮されます。SwiftUIの.animation(nil)モディファイアはreduceMotion == trueのときアニメーションを完全に無効化します。reduceMotionStatusDidChangeNotificationへの購読により、アプリを再起動せずにアニメーションを動的に切り替えられます。
iOSの別のオプション — Auto-Play Message Effects — はiMessageのエフェクト再生を制御します:バルーンのアニメーション、紙吹雪、レーザー、花火です。Reduce Motionが有効な場合、iMessageのエフェクトは自動的に無効化されます。開発者はUIAccessibility.isReduceMotionEnabledでこのオプションを確認できます — Message Effects用の別のAPIはなく、共通の設定に紐づいています。
Androidでは“アニメーションを削除”設定が2か所にあります:Settings > Accessibility > アニメーションを削除(アクセシビリティ設定用)と開発者向けオプション > アニメーションのスケール(開発者用)です。アクセシビリティ版はすべてのシステムアニメーションを無効化します(画面遷移、アプリを開くアニメーション、読み込み効果を含む)。開発者向けオプションではスケールを0.5x、0.1xに減らすか完全に無効化できます。
技術的には、Androidはシステムプロパティを通じてアニメーションの無効化を実装します:window_animation_scale、transition_animation_scale、animator_duration_scaleです。アクセシビリティ設定では3つすべてが0になります。システムのLauncherとシステムアプリはこれらの値を確認します。サードパーティアプリのために、AndroidはAnimationScaleObserverを通じてシステム設定を自動的に読み取るJetpack ComposeとViewシステムの使用を推奨しています。
開発者はAndroidでSettings.Globalを通じてアニメーションの状態を確認し、UIを適応できます。Jetpack Composeは自動調整のためのAnimationScaleObserverを提供します。重要な値はanimator_duration_scaleです:0ならアニメーションは完全に無効化されています。
import android.content.Context
import android.provider.Settings
import android.database.ContentObserver
import android.os.Handler
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.runtime.getValue
class AndroidMotionHelper {
// アニメーションが無効か確認
fun isAnimationDisabled(context: Context): Boolean {
return try {
Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE
) == 0f
} catch (e: Settings.SettingNotFoundException) {
false
}
}
// アニメーションの変更を監視(ContentObserver)
fun observeAnimationScale(
context: Context,
onChange: (Boolean) -> Unit
): ContentObserver {
val observer = object : ContentObserver(Handler()) {
override fun onChange(selfChange: Boolean) {
onChange(isAnimationDisabled(context))
}
}
context.contentResolver.registerContentObserver(
Settings.Global.getUriFor(
Settings.Global.ANIMATOR_DURATION_SCALE
),
false,
observer
)
return observer
}
}
// Jetpack Compose — 設定を考慮したアニメーション
@Composable
fun MotionAwareAnimation(enabled: Boolean) {
val context = androidx.compose.ui.platform.LocalContext.current
val noMotion = AndroidMotionHelper().isAnimationDisabled(context)
val scale by animateFloatAsState(
targetValue = if (enabled) 1f else 0f,
animationSpec = if (noMotion) {
androidx.compose.animation.core.tween(durationMillis = 0)
} else {
androidx.compose.animation.core.spring()
},
label = "scale"
)
// アニメーション付きUI
}
AndroidMotionHelperクラスはSettings.Globalを通じてANIMATOR_DURATION_SCALEを確認し、変更を追跡するContentObserverを提供し、Jetpack Composeのアニメーションを適応させます:アニメーションが無効な場合、durationMillis = 0(即時適用)です。Viewシステムでは、アニメーションを開始する前にViewPropertyAnimator.withLayer()を使用し、isAnimationDisabled()を確認してください。
Androidの“アニメーションを削除”アクセシビリティ設定は、一般ユーザーがアニメーションを無効化する唯一の方法です。開発者向けオプションは開発者のみを対象としており、非表示になっていることがあります。アクセシビリティ設定はシステムAPIを通じてすべてのアプリに確実に伝わります。開発者は開発者向けオプションではなくAccessibilityManagerに頼るべきです。
CSSメディア機能prefers-reduced-motionは、ユーザーがOSでReduce Motionを有効にしたとき、ウェブ開発者がアニメーションを無効化または置き換えられるようにします。システム設定が有効な場合ブラウザはreduceの値を伝え、設定が変更されていない場合はno-preferenceを伝えます。2020年以降、すべての現代的なブラウザでサポートされています:Chrome 74+、Safari 10.3+、Firefox 64+、Edge 79+。
MDNとW3Cの推奨 — アニメーションとともに常にprefers-reduced-motion: reduceを指定すること。Reduce Motionを有効にしたユーザーは、パルス、パララックス、自動再生のカルーセル、スケルトンの読み込みを見るべきではありません。アニメーションの代わりに静的なコンテンツを表示したり、最小限の時間のCSS transitionを使用したりできます。以下に完全な適応の例を示します。
prefers-reduced-motion: reduceの場合、ウェブページは:CSSアニメーション(@keyframes)を無効化し、CSS transitionsを即時の変化に置き換え、JavaScriptアニメーション(requestAnimationFrame)を停止し、パララックススクロールを無効化し、カルーセルとスライダーを停止し、スケルトン効果を無効化し、スピナーを静的なインジケーターに置き換えるべきです。
/* 基本アニメーション(no-preference) */
.spinner {
width: 32px;
height: 32px;
border: 3px solid #e0e0e0;
border-top-color: #0066CC;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e8e8e8 37%,
#f0f0f0 63%
);
background-size: 400% 100%;
animation: shimmer 1.4s ease infinite;
}
.parallax-bg {
transform: translateZ(-1px) scale(1.5);
transition: transform 0.3s ease-out;
}
/* Reduce Motion:すべて無効化 */
@media (prefers-reduced-motion: reduce) {
.spinner {
animation: none;
border-top-color: #0066CC;
}
.skeleton {
animation: none;
background: #f0f0f0;
}
.parallax-bg {
transform: none;
transition: none;
}
.carousel {
scroll-behavior: auto;
overflow-x: auto;
}
.fade-in {
opacity: 1;
transform: none;
}
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}CSSの例では、prefers-reduced-motion: reduce時にアニメーションのグローバルリセットを使用しています:すべてのアニメーションと遷移がduration 0.01msとiteration-count 1になります。スピナー(静的な枠線)、スケルトン(ちらつきのない灰色の背景)、パララックス(無効化)、カルーセル(smoothの代わりにscroll-behavior: auto)が個別に上書きされています。ユニバーサルセレクター*はすべての要素の保険です。
JavaScriptではmatchMedia('(prefers-reduced-motion: reduce)').matchesが利用可能です。trueの場合 — requestAnimationFrame、setInterval、またはWeb Animations APIを通じてアニメーションを実行しないでください。例:reduceMotionではスライダーは自動回転せず、ボタンだけで操作します。GSAP、Framer Motion、Anime.jsなどのライブラリは、アクセシビリティオプションを通じてこの確認をサポートしています。
WCAG 2.2(2023)は新しい基準2.3.3 Animation from Interactions(レベルAAA)を導入しました:アニメーションがユーザーの操作(クリック、スクロール、ホバー)で始まる場合、無効化可能であるか5秒を超えない必要があります。操作に関係ないアニメーション(読み込みスピナー、プログレスバー)はこの基準の対象外です。レベルAAでは、アニメーションが情報を伝える唯一の手段でなければ十分です。
基準2.3.3は、パララックススクロールと“プル・トゥ・リフレッシュ”アニメーションによる乗り物酔いの数多くの苦情を受けて追加されました。W3Cはすべてのサイトとアプリに推奨します:要素を5秒以上アニメーションさせないこと、アニメーションを無効化するスイッチを提供すること(コントロールパネルまたはprefers-reduced-motion経由)、脈動する要素と点滅する要素を使わないこと(てんかんに危険)。
WCAG 2.2に準拠するため、開発者は:prefers-reduced-motionを確認し、設定が有効なときアニメーションを無効化し、アニメーションの最大時間を5秒に設定し(無効化できない場合)、アプリ設定でアニメーションのUIスイッチを提供し、パララックス効果を唯一のナビゲーション方法にせず、すべてのブラウザとすべてのデバイスでReduce Motionを有効にしてテストする必要があります。
Reduce Motionでのアプリの動作をテストするには、次を使用します:iOS Simulator(Settings > AccessibilityでReduce Motionを有効化)、Android Emulator(“アニメーションを削除”を有効化)、Chrome DevTools(Rendering > Emulate CSS media feature prefers-reduced-motion)、Safariのウェブインスペクタ(macOSのSystem Preferences > Accessibility > DisplayでReduce Motionを有効化)。アニメーションなしでもコンテンツがアクセシブルで読みやすいことを確認してください。
よくある質問
Reduce Motion — 前庭障害のある人のためにインターフェースのアニメーション(パララックス、遷移、アイコンの拡大)を無効化するOSのアクセシビリティ機能です。Settings > Accessibilityで有効化できます。システムはUIAccessibility(iOS)、Settings.Global(Android)、またはprefers-reduced-motion(CSS)を通じてアプリに信号を送り、開発者はアニメーションを適応できます。
iPhoneでは、Reduce MotionはSettings > Accessibility > Motion > Reduce Motionで有効化します。有効化すると、壁紙のパララックス、iMessageのエフェクト、アプリを開くアニメーション、画面遷移が無効化されます(cross-fadeに置き換え)。UIKitのシステムアニメーションは再生されません。この設定はデバイスを再起動せずにすべてのアプリに適用されます。
Androidではアニメーションは2つの方法で無効化できます:Settings > Accessibility > アニメーションを削除(ユーザーに推奨)または開発者向けオプション > アニメーションのスケール — オフにします。アクセシビリティの方法はすべてのアプリが信号を受け取ることを保証します。開発者向けオプションはシステムアニメーションのみに影響し、一部のデバイスでは非表示になっている場合があります。
CSSメディア機能prefers-reduced-motion: reduceはスタイルレベルでアニメーションを無効化できます。ユニバーサルリセットを設定することを推奨します:すべての要素にanimation-duration: 0.01ms、transition-duration: 0.01ms、animation-iteration-count: 1。特定のコンポーネント(スピナー、スケルトン、パララックス)は個別に上書きします。JavaScriptはmatchMedia('(prefers-reduced-motion: reduce)')で確認します。
WCAG 2.2の基準2.3.3(AAA)は、ユーザーの操作で始まるアニメーションが無効化可能であるか5秒を超えないことを要求します。AAでは、アニメーションが情報を伝える唯一の手段でなければ十分です。常にprefers-reduced-motionを確認し、アプリ設定でアニメーションのUIスイッチを提供することを推奨します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。