Guideline 4.0

Guideline 4.0 - Design: Reduced Motion Setting Not Respected

Low RiskEasyTypical Fix: 2-4 hours0 Reports
Also known as:Parallax scrolling effects persist with Reduce Motion enabledSpinning or rotating loading indicators do not simplifyScreen transition animations (zoom, slide, flip) ignore the settingAuto-playing animated backgrounds or hero banners continue animatingLottie or Rive animations play at full complexity regardless of accessibility preference

Our Take

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.

Resolution Guide

01

**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

```

02

**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

}

```

03

**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)

}

```

04

**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()

}

```

05

**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

}

}

```

06

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


07

**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.


Example Rejection Email

From:Apple App Review Team
Subject:Guideline 4.0 - Design: Reduced Motion Setting Not Respe
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.

Consider Appealing

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.

Generate Appeal

Before & After

Before — Rejected

// 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 — Approved

// 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

}

}

}

}

}

What changed: 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 — Rejected

// 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 — Approved

// 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)

}

}

}

}

What changed: 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.

Community Solutions · 0

Sign in to share your solution.

More Guideline 4 (Design) rejections

View all Guideline 4 rejections