Reduce Motion — en accessibility-funktion i operativsystem och webbläsare som stänger av eller minskar gränssnittsanimation för att förhindra obehag hos användare med vestibulära störningar. I iOS finns inställningen i Settings > Accessibility > Motion > Reduce Motion och stänger av parallax, animation av övergångar mellan skärmar och ikoneffekter. I Android finns det motsvarande alternativet "Ta bort animation" i Inställningar > Tillgänglighet. Enligt data från W3C WCAG 2.2 kan överdriven animation orsaka illamående, yrsel och migrän hos 15–35% av personer med vestibulära störningar.
Huvudpunkter
Reduce Motion — en systeminställning som ålägger operativsystemet, webbläsaren och applikationer att minimera eller helt stänga av animation, rörelse, skalning och parallaxtag. Funktionen är avsedd för personer med vestibulära störningar, hos vilka rörliga gränssnittselement orsakar illamående, yrsel, desorientering och migrän.
Det vestibulära systemet i innerörat ansvarar för balanssinne och orientering i rummet. När ögonen ser rörelse på skärmen men det vestibulära organet inte känner av motsvarande kroppsrörelse uppstår en sensorisk konflikt. Denna konflikt utlöser en vegetativ reaktion: illamående, kallsvett, yrsel. Enligt Vestibular Disorders Association upplever cirka 35% av personer över 40 år obehag från rörelseeffekter i gränssnitt.
Den viktigaste skillnaden med Reduce Motion jämfört med enkel avstängning av animation — systemnivån. Den aktiverade inställningen förs vidare till alla applikationer och webbplatser via operativsystemets API eller CSS-mediafunktionen prefers-reduced-motion. Utvecklaren behöver inte gissa om användaren vill ha animation — systemet meddelar detta. Detta är en del av progressive enhancement-strategin: animation är en förbättring, inte ett obligatoriskt element.
Reduce Motion påverkar parallaxtag (bakgrundsförskjutning vid lutning av enheten), animation av övergångar mellan skärmar (push, slide, fade), skalning av ikoner vid tryckning, meddelandeeffekter (SMS-bubblor), laddningsanimation (spinner, skeleton, progress bar animation), parallax i spel och webbefekter som parallax scrolling. Statiska bilder och videor påverkas inte.
| Animationstyp | iOS Reduce Motion | Android Remove Animation | CSS prefers-reduced-motion |
|---|---|---|---|
| Bakgrundsparallax | Stänger av | Stänger av | N/A |
| Övergångar mellan skärmar | Ersätter med fade | Stänger av | CSS transitions |
| Ikonanimation | Stänger av | Påverkar inte | CSS animations |
| Laddningsspinner | Påverkar inte | Stänger av | CSS animations |
| Skeleton-skärmar | Påverkar inte | Ersätter med static | CSS animations |
Huvudmålgruppen för Reduce Motion — personer med vestibulära störningar (Menières sjukdom, labyrintit, BPPV), migrän (särskilt med aura), kinetos (åksjuka i transport) och vissa former av epilepsi. Funktionen är också användbar för äldre användare — åldersrelaterade förändringar i det vestibulära organet ökar känsligheten för rörelse, och för användare med ADHD — rörliga element distraherar från läsning.
I iOS finns Reduce Motion i Settings > Accessibility > Motion och omfattar tre alternativ: Reduce Motion (huvudomkopplare), Auto-Play Message Effects (automatisk uppspelning av iMessage-effekter) och Auto-Play Video Previews (automatisk förhandsvisning av videor i App Store). Reduce Motion är kraftfullast: det stänger av bakgrundsparallax, animation av appöppning (zoom), övergångar mellan skärmar (push ersätts med cross-fade) och ikoneffekter på hemskärmen.
Tekniskt implementerar iOS Reduce Motion på UIKit-nivå genom UIView animations och UIViewControllerAnimatedTransitioning. När inställningen är aktiverad reduceras UIView.animate med varaktighet > 0 till 0,01 sek och UIViewController.transitionDuration returnerar 0. För parallax stänger iOS av UIInterpolatingMotionEffect på UIWindow. Utvecklaren kan kontrollera status via UIAccessibility.isReduceMotionEnabled.
Utvecklaren kan anpassa animation i iOS för Reduce Motion: ersätta komplexa övergångar med fade-effekter, stänga av parallax i anpassade UI-komponenter och förkorta animationernas varaktighet. SwiftUI tillhandahåller en speciell modifierare .animation(nil) när reduceMotion är aktiv.
import UIKit
class MotionManager {
// Kontrollera Reduce Motion-status
static var isReduceMotionEnabled: Bool {
return UIAccessibility.isReduceMotionEnabled
}
// Säker animation med hänsyn till 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 — modifierare för 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 }
}
}
// Prenumerera på Reduce Motion-ändring
NotificationCenter.default.addObserver(
self,
selector: #selector(motionStatusChanged),
name: UIAccessibility.reduceMotionStatusDidChangeNotification,
object: nil
)Klassen MotionManager kontrollerar isReduceMotionEnabled och anpassar animationens varaktighet: när Reduce Motion är aktiv reduceras varaktigheten till 0,01 sek (praktiskt taget omedelbart). SwiftUI-modifieraren .animation(nil) stänger helt av animation när reduceMotion == true. Prenumeration på reduceMotionStatusDidChangeNotification möjliggör dynamisk växling av animation utan att ladda om appen.
Ett separat iOS-alternativ — Auto-Play Message Effects — styr uppspelning av effekter i iMessage: ballonganimation, konfetti, lasrar och fyrverkerier. När Reduce Motion är aktiverat stängs iMessage-effekter automatiskt av. Utvecklaren kan kontrollera detta alternativ via UIAccessibility.isReduceMotionEnabled — det finns inget separat API för Message Effects, de är kopplade till den allmänna inställningen.
I Android finns inställningen "Ta bort animation" på två ställen: Inställningar > Tillgänglighet > Ta bort animation (för tillgänglighetsinställningar) och Utvecklaralternativ > Animationsskala (för utvecklare). Tillgänglighetsversionen stänger av alla systemanimationer, inklusive övergångar mellan skärmar, animation av appöppning och laddningseffekter. Utvecklaralternativ gör det möjligt att minska skalan till 0,5x, 0,1x eller stänga av helt.
Tekniskt implementerar Android avstängning av animation genom systemegenskaper: window_animation_scale, transition_animation_scale och animator_duration_scale. Vid tillgänglighetsinställningen får alla tre värdet 0. Systemets startprogram och systemappar kontrollerar dessa värden. För tredjepartsappar rekommenderar Android att använda Jetpack Compose och View system, som automatiskt läser systeminställningen via AnimationScaleObserver.
Utvecklaren kan kontrollera animationsstatus i Android via Settings.Global och anpassa gränssnittet. Jetpack Compose tillhandahåller AnimationScaleObserver för automatisk anpassning. Nyckelvärdet — animator_duration_scale: om det är 0 är animation helt avstängd.
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 {
// Kontrollera avstängning av animation
fun isAnimationDisabled(context: Context): Boolean {
return try {
Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE
) == 0f
} catch (e: Settings.SettingNotFoundException) {
false
}
}
// Observera animationsändring (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 med hänsyn till inställningar
@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 med animation
}
Klassen AndroidMotionHelper kontrollerar ANIMATOR_DURATION_SCALE via Settings.Global, tillhandahåller en ContentObserver för att spåra ändringar och gör det möjligt för Jetpack Compose-animationer att anpassa sig: när animation är avstängd är durationMillis = 0 (omedelbar tillämpning). För View-systemet, använd ViewPropertyAnimator.withLayer() och kontrollera isAnimationDisabled() innan du startar animation.
Tillgänglighetsinställningen "Ta bort animation" i Android — det enda sättet för en vanlig användare att stänga av animation. Utvecklaralternativ är endast avsedda för utvecklare och kan vara dolda. Tillgänglighetsinställningen garanteras att förmedlas till alla appar via systemets API. Utvecklaren bör förlita sig på AccessibilityManager, inte på Utvecklaralternativ.
CSS-mediafunktionen prefers-reduced-motion gör det möjligt för webbutvecklare att stänga av eller ersätta animation när användaren har aktiverat Reduce Motion i operativsystemet. Webbläsaren skickar värdet reduce vid aktiv systeminställning, no-preference — om inställningen inte har ändrats. Stöds av alla moderna webbläsare sedan 2020: Chrome 74+, Safari 10.3+, Firefox 64+, Edge 79+.
Rekommendation från MDN och W3C — ställ alltid in prefers-reduced-motion: reduce tillsammans med animationer. En användare som har aktiverat Reduce Motion bör inte se pulsering, parallax, automatisk uppspelning av karuseller och skeleton-laddning. Istället för animation kan statiskt innehåll visas eller CSS transition med minimal varaktighet användas. Nedan finns ett exempel på fullständig anpassning.
Vid prefers-reduced-motion: reduce bör webbsidan: stänga av CSS-animationer (@keyframes), ersätta CSS transitions med omedelbara ändringar, stoppa JavaScript-animationer (requestAnimationFrame), stänga av parallax scrolling, stoppa karuseller och reglage, stänga av skeleton-effekter och ersätta spinner med en statisk indikator.
/* Grundläggande animationer (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: stänger av allt */
@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; }
}I CSS-exemplet används en global återställning av animation vid prefers-reduced-motion: reduce: alla animationer och övergångar får duration 0.01ms och iteration-count 1. Separat har spinner (statisk ram), skeleton (grå bakgrund utan blinkning), parallax (avstängd) och karusell (scroll-behavior: auto istället för smooth) åsidosatts. Universalväljaren * — säkerhet för alla element.
För JavaScript finns matchMedia('(prefers-reduced-motion: reduce)').matches. Om true — starta inte animationer via requestAnimationFrame, setInterval eller Web Animations API. Exempel: ett reglage med reduceMotion roterar inte automatiskt, endast via knappar. Biblioteken GSAP, Framer Motion och Anime.js stöder denna kontroll via sina tillgänglighetsalternativ.
WCAG 2.2 (2023) introducerade ett nytt kriterium 2.3.3 Animation from Interactions (nivå AAA): om animation utlöses av användarinteraktion (klick, rullning, hover) måste den kunna stängas av eller inte överstiga 5 sekunder. Animation som inte är relaterad till interaktion (laddningsspinner, förloppsindikator) faller inte under detta kriterium. För nivå AA räcker det att animation inte är det enda sättet att förmedla information.
Kriterium 2.3.3 lades till efter många klagomål på åksjuka från parallax scrolling och "drag-uppdatera"-animation. W3C rekommenderar alla webbplatser och appar: animera inte element längre än 5 sekunder, tillhandahåll en strömbrytare för avstängning av animation (via kontrollpanel eller prefers-reduced-motion), använd inte pulserande och blinkande element (farligt för epilepsi).
För överensstämmelse med WCAG 2.2 bör utvecklaren: kontrollera prefers-reduced-motion och stänga av animation vid aktiv inställning, ställa in maximal animationstid till 5 sekunder (om animation inte kan stängas av), tillhandahålla en UI-omkopplare för animation i appens inställningar, inte använda parallaxtag som enda navigeringsmetod och testa med Reduce Motion aktiverat i alla webbläsare och på alla enheter.
För att testa appens beteende med Reduce Motion använd: iOS Simulator (aktivera Reduce Motion i Settings > Accessibility), Android Emulator (aktivera "Ta bort animation"), Chrome DevTools (Rendering > Emulate CSS media feature prefers-reduced-motion), Safari webbinspektör (aktivera Reduce Motion i macOS System Preferences > Accessibility > Display). Kontrollera att innehållet förblir tillgängligt och läsbart utan animation.
Vanliga frågor
Reduce Motion — en tillgänglighetsfunktion i operativsystemet som stänger av gränssnittsanimation (parallax, övergångar, ikonskalning) för personer med vestibulära störningar. Aktiveras i Settings > Accessibility. Systemet skickar signal till appar via UIAccessibility (iOS), Settings.Global (Android) eller prefers-reduced-motion (CSS), och utvecklaren kan anpassa animationen.
På iPhone aktiveras Reduce Motion i Settings > Accessibility > Motion > Reduce Motion. Efter aktivering stängs följande av: bakgrundsparallax, iMessage-effekter, animation av appöppning och övergångar mellan skärmar (ersätts med cross-fade). Systemanimationer i UIKit spelas inte upp. Inställningen tillämpas på alla appar utan omstart av enheten.
I Android stängs animation av på två sätt: Inställningar > Tillgänglighet > Ta bort animation (rekommenderas för användare) eller Utvecklaralternativ > Animationsskala — stäng av. Tillgänglighetsmetoden garanterar att alla appar får signalen. Utvecklaralternativ påverkar endast systemanimationer och kan vara dolda på vissa enheter.
CSS-mediafunktionen prefers-reduced-motion: reduce gör det möjligt att stänga av animation på stilmallsnivå. Det rekommenderas att ställa in en universell återställning: animation-duration: 0.01ms, transition-duration: 0.01ms, animation-iteration-count: 1 för alla element. Åsidosätt separat specifika komponenter (spinner, skeleton, parallax). JavaScript kontrolleras via matchMedia('(prefers-reduced-motion: reduce)').
WCAG 2.2 kriterium 2.3.3 (AAA) kräver att animation som utlöses av användarinteraktion måste kunna stängas av eller inte överstiga 5 sekunder. För AA räcker det att animation inte är det enda sättet att förmedla information. Det rekommenderas att alltid kontrollera prefers-reduced-motion och tillhandahålla en UI-omkopplare för animation i appens inställningar.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också