Reduce Motion — funcția accessibility a sistemelor de operare și browserelor care dezactivează sau reduce animația interfeței pentru a preveni disconfortul utilizatorilor cu tulburări vestibulare. În iOS setarea se află în Settings > Accessibility > Motion > Reduce Motion și dezactivează paralaxa, animația tranzițiilor între ecrane și efectele pictogramelor. În Android opțiunea analogică „Șterge animația” se află în Setări > Accesibilitate. Conform datelor W3C WCAG 2.2, animația excesivă poate provoca greață, amețeli și migrenă la 15–35% dintre persoanele cu tulburări vestibulare.
Principalele puncte
Reduce Motion — o setare de sistem care solicită sistemului de operare, browserului și aplicațiilor să minimizeze sau să dezactiveze complet animația, mișcarea, scalarea și efectele de paralaxă. Funcția este destinată persoanelor cu tulburări vestibulare, la care elementele în mișcare ale interfeței provoacă greață, amețeli, dezorientare și migrenă.
Sistemul vestibular urechii interne este responsabil pentru simțul echilibrului și orientarea în spațiu. Când ochii văd mișcare pe ecran, dar aparatul vestibular nu simte deplasarea corespunzătoare a corpului, apare un conflict senzorial. Acest conflict declanșează o reacție vegetativă: greață, transpirație rece, amețeli. Potrivit Asociației Tulburărilor Vestibulare, aproximativ 35% dintre persoanele peste 40 de ani experimentează disconfort din cauza efectelor de mișcare în interfețe.
Diferența cheie a Reduce Motion față de simpla dezactivare a animației — nivelul de sistem. Setarea activată este transmisă tuturor aplicațiilor și site-urilor web prin API-ul sistemului de operare sau funcția media CSS prefers-reduced-motion. Dezvoltatorul nu trebuie să ghicească dacă utilizatorul dorește animație — sistemul îl informează. Aceasta face parte din abordarea progressive enhancement: animația este o îmbunătățire, nu un element obligatoriu.
Reduce Motion afectează efectele de paralaxă (deplasarea fundalului la înclinarea dispozitivului), animația tranzițiilor între ecrane (push, slide, fade), scalarea pictogramelor la apăsare, efectele mesajelor (bule SMS), animația de încărcare (spinner, skeleton, progress bar animation), paralaxa în jocuri și efectele de parallax scrolling web. Imaginile statice și videoclipurile nu sunt afectate.
| Tipul animației | iOS Reduce Motion | Android Remove Animation | CSS prefers-reduced-motion |
|---|---|---|---|
| Paralaxa tapetului | Dezactivează | Dezactivează | N/A |
| Tranziții între ecrane | Înlocuiește cu fade | Dezactivează | CSS transitions |
| Animația pictogramelor | Dezactivează | Nu afectează | CSS animations |
| Spinner de încărcare | Nu afectează | Dezactivează | CSS animations |
| Ecrane skeleton | Nu afectează | Înlocuiește cu static | CSS animations |
Publicul țintă principal al Reduce Motion — persoane cu tulburări vestibulare (boala Meniere, labirintită, BPPV), migrenă (în special cu aură), kinetoză (rău de mișcare în transport) și unele forme de epilepsie. Funcția este utilă și pentru utilizatorii în vârstă — modificările legate de vârstă ale aparatului vestibular cresc sensibilitatea la mișcare, precum și pentru utilizatorii cu ADHD — elementele în mișcare distrag atenția de la citire.
În iOS Reduce Motion se află în Settings > Accessibility > Motion și include trei opțiuni: Reduce Motion (comutatorul principal), Auto-Play Message Effects (redarea automată a efectelor iMessage) și Auto-Play Video Previews (previzualizarea automată a videoclipurilor în App Store). Reduce Motion este cel mai puternic: dezactivează paralaxa tapetului, animația de deschidere a aplicațiilor (zoom), tranzițiile între ecrane (push este înlocuit cu cross-fade) și efectele pictogramelor pe ecranul principal.
Din punct de vedere tehnic iOS implementează Reduce Motion la nivelul UIKit prin UIView animations și UIViewControllerAnimatedTransitioning. Cu setarea activată, UIView.animate cu durata > 0 este redus la 0,01 sec, iar UIViewController.transitionDuration returnează 0. Pentru paralaxă, iOS dezactivează UIInterpolatingMotionEffect pe UIWindow. Dezvoltatorul poate verifica starea prin UIAccessibility.isReduceMotionEnabled.
Dezvoltatorul poate adapta animația în iOS la Reduce Motion: înlocui tranzițiile complexe cu efecte fade, dezactiva paralaxa în componentele UI personalizate și scurta durata animațiilor. SwiftUI oferă un modificator special .animation(nil) când reduceMotion este activ.
import UIKit
class MotionManager {
// Verificarea stării Reduce Motion
static var isReduceMotionEnabled: Bool {
return UIAccessibility.isReduceMotionEnabled
}
// Animație sigură ținând cont de 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 — modificator pentru 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 }
}
}
// Abonare la modificarea Reduce Motion
NotificationCenter.default.addObserver(
self,
selector: #selector(motionStatusChanged),
name: UIAccessibility.reduceMotionStatusDidChangeNotification,
object: nil
)Clasa MotionManager verifică isReduceMotionEnabled și adaptează durata animației: cu Reduce Motion activ, durata este redusă la 0,01 sec (practic instantaneu). Modificatorul SwiftUI .animation(nil) dezactivează complet animația când reduceMotion == true. Abonarea la reduceMotionStatusDidChangeNotification permite comutarea dinamică a animației fără reîncărcarea aplicației.
O opțiune separată iOS — Auto-Play Message Effects — controlează redarea efectelor în iMessage: animația baloanelor, confetti, lasere și artificii. Cu Reduce Motion activ, efectele iMessage sunt dezactivate automat. Dezvoltatorul poate verifica această opțiune prin UIAccessibility.isReduceMotionEnabled — nu există un API separat pentru Message Effects, acestea sunt legate de setarea generală.
În Android setarea „Șterge animația” se află în două locuri: Setări > Accesibilitate > Șterge animația (pentru setările de accesibilitate) și Opțiuni dezvoltator > Scara animației (pentru dezvoltatori). Versiunea de accesibilitate dezactivează toate animațiile de sistem, inclusiv tranzițiile între ecrane, animația de deschidere a aplicațiilor și efectele de încărcare. Opțiunile dezvoltator permit reducerea scării la 0,5x, 0,1x sau dezactivarea completă.
Din punct de vedere tehnic Android implementează dezactivarea animației prin proprietăți de sistem: window_animation_scale, transition_animation_scale și animator_duration_scale. La setarea de accesibilitate, toate trei primesc valoarea 0. Lansatorul de sistem și aplicațiile de sistem verifică aceste valori. Pentru aplicațiile terțe, Android recomandă utilizarea Jetpack Compose și View system, care citesc automat setarea de sistem prin AnimationScaleObserver.
Dezvoltatorul poate verifica starea animației în Android prin Settings.Global și adapta UI. Jetpack Compose oferă AnimationScaleObserver pentru adaptarea automată. Valoarea cheie — animator_duration_scale: dacă este 0, animația este complet dezactivată.
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 {
// Verificarea dezactivării animației
fun isAnimationDisabled(context: Context): Boolean {
return try {
Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE
) == 0f
} catch (e: Settings.SettingNotFoundException) {
false
}
}
// Observarea modificării animației (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 — animație ținând cont de setări
@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"
)
// Interfață cu animație
}
Clasa AndroidMotionHelper verifică ANIMATOR_DURATION_SCALE prin Settings.Global, oferă ContentObserver pentru urmărirea modificărilor și permite animațiilor Jetpack Compose să se adapteze: cu animația dezactivată, durationMillis = 0 (aplicare instantanee). Pentru sistemul View, utilizați ViewPropertyAnimator.withLayer() și verificați isAnimationDisabled() înainte de a porni animația.
Setarea de accesibilitate „Șterge animația” în Android — singura modalitate pentru utilizatorul obișnuit de a dezactiva animația. Opțiunile dezvoltator sunt destinate exclusiv dezvoltatorilor și pot fi ascunse. Setarea de accesibilitate este garantată a fi transmisă tuturor aplicațiilor prin API-ul de sistem. Dezvoltatorul ar trebui să se orienteze după AccessibilityManager, nu după Opțiunile dezvoltator.
Funcția media CSS prefers-reduced-motion permite dezvoltatorilor web să dezactiveze sau să înlocuiască animația atunci când utilizatorul a activat Reduce Motion în sistemul de operare. Browserul transmite valoarea reduce la setarea de sistem activă, no-preference — dacă setarea nu a fost modificată. Este suportată de toate browserele moderne din 2020: Chrome 74+, Safari 10.3+, Firefox 64+, Edge 79+.
Recomandarea MDN și W3C — setați întotdeauna prefers-reduced-motion: reduce împreună cu animațiile. Utilizatorul care a activat Reduce Motion nu ar trebui să vadă pulsații, paralaxă, redarea automată a caruselurilor și încărcarea skeleton. În locul animației se poate afișa conținut static sau se poate utiliza CSS transition cu durată minimă. Mai jos este un exemplu de adaptare completă.
La prefers-reduced-motion: reduce pagina web trebuie să: dezactiveze animațiile CSS (@keyframes), înlocuiască CSS transitions cu modificări instantanee, oprească animațiile JavaScript (requestAnimationFrame), dezactiveze parallax scrolling, oprească caruselurile și glisorele, dezactiveze efectele skeleton și înlocuiască spinner-ul cu un indicator static.
/* Animații de bază (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: dezactivăm totul */
@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; }
}În exemplul CSS se utilizează o resetare globală a animației la prefers-reduced-motion: reduce: toate animațiile și tranzițiile primesc duration 0.01ms și iteration-count 1. Au fost redefinite separat spinner (border static), skeleton (fundal gri fără pâlpâire), paralaxa (dezactivată) și carusel (scroll-behavior: auto în loc de smooth). Selectorul universal * — protecție pentru toate elementele.
Pentru JavaScript este disponibil matchMedia('(prefers-reduced-motion: reduce)').matches. Dacă este true — nu rula animații prin requestAnimationFrame, setInterval sau Web Animations API. Exemplu: glisorul cu reduceMotion nu se rotește automat, ci doar prin butoane. Bibliotecile GSAP, Framer Motion și Anime.js suportă această verificare prin opțiunile lor de accesibilitate.
WCAG 2.2 (2023) a introdus criteriul nou 2.3.3 Animation from Interactions (nivel AAA): dacă animația este declanșată de interacțiunea utilizatorului (clic, derulare, hover), aceasta trebuie să poată fi dezactivată sau să nu depășească 5 secunde. Animația necorelată cu interacțiunea (spinner de încărcare, progress bar) nu intră sub acest criteriu. Pentru nivelul AA este suficient ca animația să nu fie singurul mod de transmitere a informației.
Criteriul 2.3.3 a fost adăugat după numeroase plângeri privind răul de mișcare cauzat de parallax scrolling și animația „trageți-reîmprospătați”. W3C recomandă tuturor site-urilor și aplicațiilor: nu animați elementele mai mult de 5 secunde, oferiți un comutator de dezactivare a animației (prin panoul de control sau prefers-reduced-motion), nu utilizați elemente pulsatorii și intermitente (periculoase pentru epilepsie).
Pentru conformitatea cu WCAG 2.2 dezvoltatorul trebuie să: verifice prefers-reduced-motion și dezactiveze animația la setarea activă, stabilească durata maximă a animației la 5 secunde (dacă animația nu poate fi dezactivată), ofere un comutator UI al animației în setările aplicației, nu utilizeze efectele de paralaxă ca unic mod de navigare și testeze cu Reduce Motion activat în toate browserele și pe toate dispozitivele.
Pentru testarea comportamentului aplicației cu Reduce Motion utilizați: iOS Simulator (activați Reduce Motion în Settings > Accessibility), Android Emulator (activați „Șterge animația”), Chrome DevTools (Rendering > Emulate CSS media feature prefers-reduced-motion), inspectorul web Safari (activați Reduce Motion în macOS System Preferences > Accessibility > Display). Verificați că conținutul rămâne accesibil și lizibil fără animație.
Întrebări frecvente
Reduce Motion — funcția accessibility a sistemului de operare care dezactivează animația interfeței (paralaxă, tranziții, scalare pictograme) pentru persoanele cu tulburări vestibulare. Se activează în Settings > Accessibility. Sistemul transmite semnalul aplicațiilor prin UIAccessibility (iOS), Settings.Global (Android) sau prefers-reduced-motion (CSS), iar dezvoltatorul poate adapta animația.
Pe iPhone Reduce Motion se activează în Settings > Accessibility > Motion > Reduce Motion. După activare, sunt dezactivate: paralaxa tapetului, efectele iMessage, animația de deschidere a aplicațiilor și tranzițiile între ecrane (înlocuite cu cross-fade). Animațiile de sistem UIKit nu sunt redate. Setarea se aplică tuturor aplicațiilor fără a reporni dispozitivul.
În Android animația se dezactivează în două moduri: Setări > Accesibilitate > Șterge animația (recomandat pentru utilizatori) sau Opțiuni dezvoltator > Scara animației — dezactivați. Metoda de accesibilitate garantează că toate aplicațiile primesc semnalul. Opțiunile dezvoltator afectează doar animațiile de sistem și pot fi ascunse pe unele dispozitive.
Funcția media CSS prefers-reduced-motion: reduce permite dezactivarea animației la nivelul stilurilor. Se recomandă setarea unei resetări universale: animation-duration: 0.01ms, transition-duration: 0.01ms, animation-iteration-count: 1 pentru toate elementele. Redefiniți separat componentele specifice (spinner, skeleton, paralaxă). JavaScript se verifică prin matchMedia('(prefers-reduced-motion: reduce)').
WCAG 2.2 criteriul 2.3.3 (AAA) cere ca animația declanșată de interacțiunea utilizatorului să poată fi dezactivată sau să nu depășească 5 secunde. Pentru AA este suficient ca animația să nu fie singurul mod de transmitere a informației. Se recomandă verificarea întotdeauna a prefers-reduced-motion și oferirea unui comutator UI al animației în setările aplicației.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și