# Guideline 4.0 - Design: Reduced Motion Setting Not Respected

**Guideline:** 4.0 · **Store:** Apple App Store · **Risk:** low · **Difficulty:** easy · **Typical turnaround:** 2-4 hours

Canonical URL: https://appstorereject.com/rejections/apple/4/guideline-40-design-reduced-motion-setting-not-respected

## Description

Apple rejected your app because it does not respect the Reduce Motion accessibility setting. When users enable Settings → Accessibility → Motion → Reduce Motion, your app continues to display parallax effects, spinning animations, zoom transitions, or other motion-intensive UI. Users with vestibular disorders or motion sensitivity rely on this setting to prevent dizziness and nausea. Apple expects all apps to detect the Reduce Motion preference and provide simplified, crossfade-style alternatives for every animation.

## Common variations

- Parallax scrolling effects persist with Reduce Motion enabled
- Spinning or rotating loading indicators do not simplify
- Screen transition animations (zoom, slide, flip) ignore the setting
- Auto-playing animated backgrounds or hero banners continue animating
- Lottie or Rive animations play at full complexity regardless of accessibility preference

## Example rejection email

```
Your app does not respect the Reduce Motion accessibility setting.

Specifically, when the reviewer enabled Reduce Motion in Settings → Accessibility → Motion, the following animations continued to play: (1) the spinning loading indicator on the home screen, (2) parallax scrolling effects on the featured content cards, and (3) the zoom-in transition between screens. Please update your app to detect the Reduce Motion setting and provide appropriate alternatives for all animations.
```

## Resolution steps

## How to Fix Reduced Motion Setting Not Respected

1. **Detect the Reduce Motion preference** — In SwiftUI, use the environment value:

   ```swift
   @Environment(\.accessibilityReduceMotion) var reduceMotion
   ```

   In UIKit, check the static property:

   ```swift
   UIAccessibility.isReduceMotionEnabled
   ```

2. **Replace complex animations with crossfades** — When Reduce Motion is on, swap zoom, spin, and slide animations for simple opacity transitions:

   ```swift
   withAnimation(reduceMotion ? .none : .spring(duration: 0.4)) {
       showDetail = true
   }
   ```

3. **Disable parallax effects** — Remove any custom parallax layers or set their motion multiplier to zero when Reduce Motion is enabled. If using UIInterpolatingMotionEffect, guard it:

   ```swift
   if !UIAccessibility.isReduceMotionEnabled {
       view.addMotionEffect(parallaxEffect)
   }
   ```

4. **Simplify loading indicators** — Replace spinning indicators with a static pulsing dot or a simple progress bar:

   ```swift
   if reduceMotion {
       ProgressView()  // system default respects Reduce Motion
   } else {
       CustomSpinnerView()
   }
   ```

5. **Use the .transaction modifier for view transitions** — SwiftUI’s matchedGeometryEffect and NavigationStack transitions can be made motion-safe:

   ```swift
   .transaction { transaction in
       if reduceMotion {
           transaction.animation = nil
       }
   }
   ```

6. **Audit all Lottie/Rive animations** — Either pause animated assets entirely or switch to a simplified, low-motion variant when Reduce Motion is enabled.

7. **Test with Reduce Motion enabled** — Go to Settings → Accessibility → Motion → Reduce Motion and walk through every screen. No spinning, zooming, parallax, or auto-play animation should be visible.

## Appeal guidance

Do not appeal. This is a straightforward accessibility fix that typically takes 2–4 hours. Check the @Environment(\.accessibilityReduceMotion) value and provide crossfade or static alternatives for every animation. Resubmit once the fix is verified with Reduce Motion enabled.

## Before / after examples

**Before:** // Spinning loader that ignores Reduce Motion
struct SpinnerView: View {
    @State private var rotation: Double = 0

    var body: some View {
        Image(systemName: "arrow.triangle.2.circlepath")
            .rotationEffect(.degrees(rotation))
            .onAppear {
                withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) {
                    rotation = 360
                }
            }
    }
}
**After:** // Motion-safe spinner with Reduce Motion fallback
struct SpinnerView: View {
    @State private var rotation: Double = 0
    @Environment(\.accessibilityReduceMotion) var reduceMotion

    var body: some View {
        if reduceMotion {
            ProgressView()  // system spinner respects Reduce Motion
        } else {
            Image(systemName: "arrow.triangle.2.circlepath")
                .rotationEffect(.degrees(rotation))
                .onAppear {
                    withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) {
                        rotation = 360
                    }
                }
        }
    }
}
**Why it works:** When Reduce Motion is enabled, replace the custom spinning animation with the system ProgressView, which automatically adapts to accessibility settings. The custom spinner only runs when the user has not requested reduced motion.

**Before:** // Parallax card effect on scroll — ignores accessibility
struct ParallaxCard: View {
    let offset: CGFloat

    var body: some View {
        ZStack {
            Image("background")
                .offset(y: offset * 0.3)  // parallax movement
            VStack {
                Text("Featured")
                    .font(.title)
            }
        }
    }
}
**After:** // Parallax card with Reduce Motion guard
struct ParallaxCard: View {
    let offset: CGFloat
    @Environment(\.accessibilityReduceMotion) var reduceMotion

    var body: some View {
        ZStack {
            Image("background")
                .offset(y: reduceMotion ? 0 : offset * 0.3)
            VStack {
                Text("Featured")
                    .font(.title)
            }
        }
    }
}
**Why it works:** The parallax offset multiplier is set to zero when Reduce Motion is enabled. The background image stays fixed while the content scrolls normally, eliminating the motion that can cause vestibular discomfort.

## Common questions

**Can you appeal a 4.0 rejection?**

Do not appeal. This is a straightforward accessibility fix that typically takes 2–4 hours. Check the @Environment(\.accessibilityReduceMotion) value and provide crossfade or static alternatives for every animation. Resubmit once the fix is verified with Reduce Motion enabled.

**How long does this typically take to fix?**

Typical turnaround is 2-4 hours (difficulty: easy). After resubmission, most re-reviews complete within 24-48 hours.

---
*Machine-readable source: https://api.appstorereject.com/api/rejections/detail?slug=guideline-40-design-reduced-motion-setting-not-respected*