Reduce Motion in mobile apps: the essentials of reduced-motion settings

Author: IT Sectr Published: 2026-05-16 Reading time: 12 min

Reduce Motion — an accessibility feature of operating systems and browsers that disables or reduces interface animation to prevent discomfort for users with vestibular disorders. On iOS, the setting is located in Settings > Accessibility > Motion > Reduce Motion and disables parallax, screen transition animations, and icon effects. On Android, the equivalent option “Remove animations” is located in Settings > Accessibility. According to W3C WCAG 2.2, excessive animation can cause nausea, dizziness, and migraines in 15–35% of people with vestibular disorders.

Key takeaways

  • Reduce Motion — an accessibility setting that disables interface animation for the comfort of users with vestibular disorders
  • iOS Reduce Motion — in Settings > Accessibility > Motion: disables parallax, icon transitions, and message effects
  • Android — “Remove animations” in Settings > Accessibility; disables scaling and transitions
  • CSS prefers-reduced-motion — a media feature for web developers: disables CSS animation when the system setting is active
  • WCAG 2.2 — criterion 2.3.3 requires disabling animation from interactions by default

What is Reduce Motion in accessibility?

Reduce Motion — a system setting that instructs the operating system, browser, and applications to minimize or completely disable animation, movement, scaling, and parallax effects. The feature is designed for people with vestibular disorders, in whom moving interface elements cause nausea, dizziness, disorientation, and migraine.

The vestibular system of the inner ear is responsible for the sense of balance and spatial orientation. When the eyes see movement on screen but the vestibular apparatus does not sense the corresponding movement of the body, a sensory conflict occurs. This conflict triggers an autonomic reaction: nausea, cold sweat, dizziness. According to the Vestibular Disorders Association, about 35% of people over 40 experience discomfort from motion effects in interfaces.

The key difference between Reduce Motion and simply disabling animation is the system level. When enabled, the setting is passed to all apps and websites through the OS API or the CSS media feature prefers-reduced-motion. The developer does not need to guess whether the user wants animation — the OS reports it. This is part of the progressive enhancement approach: animation is an enhancement, not a required element.

What effects does Reduce Motion disable

Reduce Motion affects parallax effects (background shifting when the device is tilted), screen transition animations (push, slide, fade), icon scaling on tap, message effects (SMS bubbles), loading animations (spinner, skeleton, progress bar animation), parallax in games, and web parallax scrolling effects. Static images and videos are not affected.

Animation type iOS Reduce Motion Android Remove Animation CSS prefers-reduced-motion
Wallpaper parallax Disables Disables N/A
Screen transitions Replaces with fade Disables CSS transitions
Icon animation Disables No effect CSS animations
Loading spinner No effect Disables CSS animations
Skeleton screens No effect Replaces with static CSS animations

Who needs Reduce Motion

The main audience for Reduce Motion is people with vestibular disorders (Ménière's disease, labyrinthitis, BPPV), migraine (especially with aura), kinetosis (motion sickness in transport), and certain forms of epilepsy. The feature is also useful for elderly users — age-related changes in the vestibular apparatus increase sensitivity to motion — and for users with ADHD, since moving elements distract from reading.

Reduce Motion on iOS: settings and system effects

On iOS, Reduce Motion is located in Settings > Accessibility > Motion and includes three options: Reduce Motion (the main switch), Auto-Play Message Effects (auto-play of iMessage effects), and Auto-Play Video Previews (auto-play of videos in the App Store). Reduce Motion is the most powerful: it disables wallpaper parallax, app open animation (zoom), screen transitions (push is replaced with cross-fade), and icon effects on the home screen.

Technically, iOS implements Reduce Motion at the UIKit level through UIView animations and UIViewControllerAnimatedTransitioning. With the setting enabled, UIView.animate with a duration > 0 is reduced to 0.01 seconds, and UIViewController.transitionDuration returns 0. For parallax, iOS disables UIInterpolatingMotionEffect on UIWindow. The developer can check the state via UIAccessibility.isReduceMotionEnabled.

Checking Reduce Motion in an iOS app

A developer can adapt animation in iOS to Reduce Motion: replace complex transitions with fade effects, disable parallax in custom UI components, and shorten animation durations. SwiftUI provides a special .animation(nil) modifier when reduceMotion is active.

swift
import UIKit

class MotionManager {

    // Checking Reduce Motion status
    static var isReduceMotionEnabled: Bool {
        return UIAccessibility.isReduceMotionEnabled
    }

    // Safe animation that respects 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 — modifier for 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 }
    }
}

// Subscribing to Reduce Motion changes
NotificationCenter.default.addObserver(
    self,
    selector: #selector(motionStatusChanged),
    name: UIAccessibility.reduceMotionStatusDidChangeNotification,
    object: nil
)

The MotionManager class checks isReduceMotionEnabled and adapts the animation duration: when Reduce Motion is active, the duration is reduced to 0.01 seconds (practically instant). The SwiftUI .animation(nil) modifier completely disables animation when reduceMotion == true. Subscribing to reduceMotionStatusDidChangeNotification allows dynamically switching animation without restarting the app.

Auto-Play Message Effects in iMessage

A separate iOS option — Auto-Play Message Effects — controls the playback of effects in iMessage: balloon animation, confetti, lasers, and fireworks. When Reduce Motion is enabled, iMessage effects are automatically disabled. A developer can check this option via UIAccessibility.isReduceMotionEnabled — there is no separate API for Message Effects; they are tied to the general setting.

Remove animations on Android: Developer Options and Accessibility

On Android, the “Remove animations” setting is located in two places: Settings > Accessibility > Remove animations (for accessibility settings) and Developer options > Animation scale (for developers). The accessibility version disables all system animations, including screen transitions, app open animation, and loading effects. Developer Options let you reduce the scale to 0.5x, 0.1x, or disable it completely.

Technically, Android implements animation disabling through system properties: window_animation_scale, transition_animation_scale, and animator_duration_scale. With the accessibility setting, all three are set to 0. The system Launcher and system apps check these values. For third-party apps, Android recommends using Jetpack Compose and the View system, which automatically read the system setting through AnimationScaleObserver.

Checking in an Android app

A developer can check the animation state on Android via Settings.Global and adapt the UI. Jetpack Compose provides AnimationScaleObserver for automatic adjustment. The key value is animator_duration_scale: if it is 0, animation is fully disabled.

kotlin
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 {

    // Checking if animation is disabled
    fun isAnimationDisabled(context: Context): Boolean {
        return try {
            Settings.Global.getFloat(
                context.contentResolver,
                Settings.Global.ANIMATOR_DURATION_SCALE
            ) == 0f
        } catch (e: Settings.SettingNotFoundException) {
            false
        }
    }

    // Observing animation changes (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 — animation that respects settings
@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 with animation
}

The AndroidMotionHelper class checks ANIMATOR_DURATION_SCALE through Settings.Global, provides a ContentObserver for tracking changes, and allows Jetpack Compose animations to adapt: when animation is disabled, durationMillis = 0 (instant application). For the View system, use ViewPropertyAnimator.withLayer() and check isAnimationDisabled() before starting an animation.

Difference between Accessibility and Developer Options

The “Remove animations” accessibility setting on Android is the only way for a regular user to disable animation. Developer Options are intended only for developers and can be hidden. The accessibility setting is guaranteed to be passed to all apps through the system API. A developer should rely on AccessibilityManager rather than Developer Options.

CSS prefers-reduced-motion: a media feature for the web

The CSS media feature prefers-reduced-motion lets web developers disable or replace animation when the user has enabled Reduce Motion in the operating system. The browser reports the value reduce when the system setting is active and no-preference when it is unchanged. It is supported by all modern browsers since 2020: Chrome 74+, Safari 10.3+, Firefox 64+, Edge 79+.

The recommendation of MDN and W3C is to always specify prefers-reduced-motion: reduce together with animations. A user who has enabled Reduce Motion should not see pulsing, parallax, auto-playing carousels, or skeleton loading. Instead of animation, you can show static content or use a CSS transition with minimal duration. Below is an example of full adaptation.

Adapting a web page through prefers-reduced-motion

With prefers-reduced-motion: reduce, a web page should: disable CSS animations (@keyframes), replace CSS transitions with instant changes, stop JavaScript animations (requestAnimationFrame), disable parallax scrolling, stop carousels and sliders, disable skeleton effects, and replace the spinner with a static indicator.

css
/* Basic animations (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: disabling everything */
@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; }
}

In the CSS example, a global animation reset is used for prefers-reduced-motion: reduce: all animations and transitions get duration 0.01ms and iteration-count 1. The spinner (static border), skeleton (gray background without flicker), parallax (disabled), and carousel (scroll-behavior: auto instead of smooth) are overridden separately. The universal selector * is a safety net for all elements.

JavaScript detection of prefers-reduced-motion

For JavaScript, matchMedia('(prefers-reduced-motion: reduce)').matches is available. If it is true — do not run animations via requestAnimationFrame, setInterval, or the Web Animations API. Example: a slider with reduceMotion does not auto-rotate, only by buttons. Libraries such as GSAP, Framer Motion, and Anime.js support this check through their accessibility options.

WCAG 2.2: animation from interactions and criterion 2.3.3

WCAG 2.2 (2023) introduced a new criterion 2.3.3 Animation from Interactions (level AAA): if animation is triggered by user interaction (click, scroll, hover), it must be disable-able or not exceed 5 seconds. Animation not related to interaction (loading spinner, progress bar) does not fall under this criterion. For level AA, it is enough that animation is not the only way to convey information.

Criterion 2.3.3 was added after numerous complaints about motion sickness from parallax scrolling and “pull-to-refresh” animation. W3C recommends all sites and apps: do not animate elements for more than 5 seconds, provide a toggle to disable animation (via a control panel or prefers-reduced-motion), and do not use pulsing and flashing elements (dangerous for epilepsy).

How to comply with WCAG 2.2 for animation

To comply with WCAG 2.2, a developer needs to: check prefers-reduced-motion and disable animation when the setting is active, set a maximum animation duration of 5 seconds (if the animation cannot be disabled), provide a UI animation toggle in the app settings, not use parallax effects as the only navigation method, and test with Reduce Motion enabled in all browsers and on all devices.

  • Checking prefers-reduced-motion — mandatory for all websites with CSS/JS animation
  • Maximum 5 seconds — animation from interactions must not last longer (criterion 2.3.3 AAA)
  • UI toggle — the app must have an option to disable animation in settings
  • No parallax navigation — content must not be accessible only through parallax scrolling

Reduce Motion testing tools

To test app behavior with Reduce Motion, use: iOS Simulator (enable Reduce Motion in Settings > Accessibility), Android Emulator (enable “Remove animations”), Chrome DevTools (Rendering > Emulate CSS media feature prefers-reduced-motion), and the Safari web inspector (enable Reduce Motion in macOS System Preferences > Accessibility > Display). Check that content remains accessible and readable without animation.

Frequently Asked Questions

What is Reduce Motion and how does it work?

Reduce Motion — an accessibility feature of the OS that disables interface animation (parallax, transitions, icon scaling) for people with vestibular disorders. It is enabled in Settings > Accessibility. The system passes the signal to apps through UIAccessibility (iOS), Settings.Global (Android), or prefers-reduced-motion (CSS), and the developer can adapt the animation.

How do I enable Reduce Motion on an iPhone?

On an iPhone, Reduce Motion is enabled in Settings > Accessibility > Motion > Reduce Motion. Once enabled, wallpaper parallax, iMessage effects, app open animation, and screen transitions are disabled (replaced with cross-fade). System UIKit animations are not played. The setting applies to all apps without restarting the device.

How do I disable animation on Android?

On Android, animation is disabled in two ways: Settings > Accessibility > Remove animations (recommended for users) or Developer options > Animation scale — turn it off. The accessibility method guarantees that all apps receive the signal. Developer Options affect only system animations and may be hidden on some devices.

How does CSS prefers-reduced-motion disable animation on a website?

The CSS media feature prefers-reduced-motion: reduce allows disabling animation at the style level. It is recommended to set a universal reset: animation-duration: 0.01ms, transition-duration: 0.01ms, animation-iteration-count: 1 for all elements. Override specific components separately (spinner, skeleton, parallax). JavaScript is checked via matchMedia('(prefers-reduced-motion: reduce)').

What are the WCAG 2.2 requirements for animation?

WCAG 2.2 criterion 2.3.3 (AAA) requires animation triggered by user interaction to be disable-able or not exceed 5 seconds. For AA, it is enough that animation is not the only way to convey information. It is recommended to always check prefers-reduced-motion and provide a UI animation toggle in the app settings.

Summary

  • Reduce Motion — a system accessibility feature that disables animation to prevent vestibular disorders and migraine
  • iOS Reduce Motion — Settings > Accessibility > Motion; disables parallax, transitions, and icon animation
  • Android Remove Animation — Settings > Accessibility; zeroes window_animation_scale and animator_duration_scale
  • CSS prefers-reduced-motion — a media feature with a global animation reset (0.01ms, iteration-count: 1)
  • WCAG 2.2 (2.3.3) — animation from interactions no more than 5 seconds or disable-able (level AAA)
  • Checking — UIAccessibility.isReduceMotionEnabled (iOS), Settings.Global.ANIMATOR_DURATION_SCALE (Android)
  • Testing — Chrome DevTools emulation, iOS Simulator, Android Emulator, Safari web inspector

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also