Reduce Motion — une fonction d'accessibilité des systèmes d'exploitation et des navigateurs qui désactive ou réduit l'animation de l'interface pour éviter l'inconfort chez les utilisateurs souffrant de troubles vestibulaires. Sur iOS, le réglage se trouve dans Settings > Accessibility > Motion > Reduce Motion et désactive le parallaxe, les animations de transition entre les écrans et les effets d'icônes. Sur Android, l'option équivalente « Supprimer les animations » se trouve dans Settings > Accessibility. Selon W3C WCAG 2.2, une animation excessive peut provoquer nausées, vertiges et migraines chez 15 à 35 % des personnes souffrant de troubles vestibulaires.
Points clés
Reduce Motion — un réglage système qui demande au système d'exploitation, au navigateur et aux applications de minimiser ou de désactiver complètement l'animation, le mouvement, la mise à l'échelle et les effets de parallaxe. La fonction est conçue pour les personnes souffrant de troubles vestibulaires, chez qui les éléments animés de l'interface provoquent nausées, vertiges, désorientation et migraines.
Le système vestibulaire de l'oreille interne est responsable du sens de l'équilibre et de l'orientation spatiale. Lorsque les yeux voient un mouvement à l'écran mais que l'appareil vestibulaire ne perçoit pas le déplacement correspondant du corps, un conflit sensoriel se produit. Ce conflit déclenche une réaction végétative : nausées, sueurs froides, vertiges. Selon la Vestibular Disorders Association, environ 35 % des personnes de plus de 40 ans ressentent un inconfort lié aux effets de mouvement dans les interfaces.
La différence clé entre Reduce Motion et la simple désactivation des animations est le niveau système. Une fois activé, le réglage est transmis à toutes les applications et tous les sites web via l'API du système d'exploitation ou la media feature CSS prefers-reduced-motion. Le développeur n'a pas besoin de deviner si l'utilisateur veut de l'animation — le système d'exploitation l'indique. Cela fait partie de l'approche progressive enhancement : l'animation est une amélioration, pas un élément obligatoire.
Reduce Motion affecte les effets de parallaxe (décalage du fond lors de l'inclinaison de l'appareil), les animations de transition entre les écrans (push, slide, fade), la mise à l'échelle des icônes au toucher, les effets de messages (bulles SMS), les animations de chargement (spinner, skeleton, animation de barre de progression), le parallaxe dans les jeux et les effets web de parallaxe au défilement. Les images statiques et les vidéos ne sont pas affectées.
| Type d'animation | iOS Reduce Motion | Android Remove Animation | CSS prefers-reduced-motion |
|---|---|---|---|
| Parallaxe du fond d'écran | Désactive | Désactive | N/A |
| Transitions entre les écrans | Remplace par fondu | Désactive | CSS transitions |
| Animation des icônes | Désactive | Aucun effet | CSS animations |
| Spinner de chargement | Aucun effet | Désactive | CSS animations |
| Écrans skeleton | Aucun effet | Remplace par statique | CSS animations |
Le public principal de Reduce Motion regroupe les personnes souffrant de troubles vestibulaires (maladie de Ménière, labyrinthite, VPPB), de migraines (surtout avec aura), de cinétose (mal des transports) et de certaines formes d'épilepsie. La fonction est également utile pour les utilisateurs âgés — les changements liés à l'âge dans l'appareil vestibulaire augmentent la sensibilité au mouvement — et pour les utilisateurs atteints de TDAH, car les éléments animés distraient de la lecture.
Sur iOS, Reduce Motion se trouve dans Settings > Accessibility > Motion et comprend trois options : Reduce Motion (le commutateur principal), Auto-Play Message Effects (lecture automatique des effets iMessage) et Auto-Play Video Previews (lecture automatique des vidéos dans l'App Store). Reduce Motion est le plus puissant : il désactive le parallaxe du fond d'écran, l'animation d'ouverture des applications (zoom), les transitions entre les écrans (push est remplacé par cross-fade) et les effets d'icônes sur l'écran d'accueil.
Techniquement, iOS implémente Reduce Motion au niveau d'UIKit via UIView animations et UIViewControllerAnimatedTransitioning. Lorsque le réglage est activé, UIView.animate avec une durée > 0 est réduit à 0,01 seconde et UIViewController.transitionDuration renvoie 0. Pour le parallaxe, iOS désactive UIInterpolatingMotionEffect sur UIWindow. Le développeur peut vérifier l'état via UIAccessibility.isReduceMotionEnabled.
Un développeur peut adapter l'animation sur iOS à Reduce Motion : remplacer les transitions complexes par des effets de fondu, désactiver le parallaxe dans les composants UI personnalisés et raccourcir la durée des animations. SwiftUI fournit un modificateur spécial .animation(nil) lorsque reduceMotion est actif.
import UIKit
class MotionManager {
// Vérifier l'état de Reduce Motion
static var isReduceMotionEnabled: Bool {
return UIAccessibility.isReduceMotionEnabled
}
// Animation sûre respectant 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 — modificateur pour 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 }
}
}
// S'abonner aux changements de Reduce Motion
NotificationCenter.default.addObserver(
self,
selector: #selector(motionStatusChanged),
name: UIAccessibility.reduceMotionStatusDidChangeNotification,
object: nil
)La classe MotionManager vérifie isReduceMotionEnabled et adapte la durée de l'animation : lorsque Reduce Motion est actif, la durée est réduite à 0,01 seconde (pratiquement instantanée). Le modificateur SwiftUI .animation(nil) désactive complètement l'animation lorsque reduceMotion == true. L'abonnement à reduceMotionStatusDidChangeNotification permet de basculer dynamiquement l'animation sans redémarrer l'application.
Une option distincte d'iOS — Auto-Play Message Effects — contrôle la lecture des effets dans iMessage : animation de ballons, confettis, lasers et feux d'artifice. Lorsque Reduce Motion est activé, les effets iMessage sont automatiquement désactivés. Un développeur peut vérifier cette option via UIAccessibility.isReduceMotionEnabled — il n'existe pas d'API distincte pour Message Effects ; ils sont liés au réglage général.
Sur Android, le réglage « Supprimer les animations » se trouve à deux endroits : Settings > Accessibility > Supprimer les animations (pour les réglages d'accessibilité) et Options développeur > Échelle d'animation (pour les développeurs). La version accessibilité désactive toutes les animations système, y compris les transitions entre les écrans, l'animation d'ouverture des applications et les effets de chargement. Les Options développeur permettent de réduire l'échelle à 0,5x, 0,1x ou de la désactiver complètement.
Techniquement, Android implémente la désactivation des animations via des propriétés système : window_animation_scale, transition_animation_scale et animator_duration_scale. Avec le réglage d'accessibilité, les trois reçoivent la valeur 0. Le Launcher système et les applications système vérifient ces valeurs. Pour les applications tierces, Android recommande d'utiliser Jetpack Compose et le système View, qui lisent automatiquement le réglage système via AnimationScaleObserver.
Un développeur peut vérifier l'état de l'animation sur Android via Settings.Global et adapter l'UI. Jetpack Compose fournit AnimationScaleObserver pour un ajustement automatique. La valeur clé est animator_duration_scale : si elle est 0, l'animation est entièrement désactivée.
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 {
// Vérifier si l'animation est désactivée
fun isAnimationDisabled(context: Context): Boolean {
return try {
Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE
) == 0f
} catch (e: Settings.SettingNotFoundException) {
false
}
}
// Observer le changement d'animation (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 respectant les réglages
@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 avec animation
}
La classe AndroidMotionHelper vérifie ANIMATOR_DURATION_SCALE via Settings.Global, fournit un ContentObserver pour suivre les changements et permet aux animations Jetpack Compose de s'adapter : lorsque l'animation est désactivée, durationMillis = 0 (application instantanée). Pour le système View, utilisez ViewPropertyAnimator.withLayer() et vérifiez isAnimationDisabled() avant de lancer une animation.
Le réglage d'accessibilité « Supprimer les animations » sur Android est la seule façon pour un utilisateur ordinaire de désactiver l'animation. Les Options développeur sont destinées uniquement aux développeurs et peuvent être masquées. Le réglage d'accessibilité est transmis de manière garantie à toutes les applications via l'API système. Le développeur doit s'appuyer sur AccessibilityManager et non sur les Options développeur.
La media feature CSS prefers-reduced-motion permet aux développeurs web de désactiver ou de remplacer l'animation lorsque l'utilisateur a activé Reduce Motion dans le système d'exploitation. Le navigateur transmet la valeur reduce lorsque le réglage système est actif et no-preference lorsqu'il n'est pas modifié. Elle est prise en charge par tous les navigateurs modernes depuis 2020 : Chrome 74+, Safari 10.3+, Firefox 64+, Edge 79+.
La recommandation de MDN et de W3C — toujours définir prefers-reduced-motion : reduce avec les animations. Un utilisateur ayant activé Reduce Motion ne doit pas voir de pulsations, de parallaxe, de carrousels en lecture automatique ni de chargement skeleton. Au lieu de l'animation, on peut afficher du contenu statique ou utiliser une transition CSS de durée minimale. Voici un exemple d'adaptation complète.
Avec prefers-reduced-motion : reduce, une page web doit : désactiver les animations CSS (@keyframes), remplacer les transitions CSS par des changements instantanés, arrêter les animations JavaScript (requestAnimationFrame), désactiver le parallaxe au défilement, arrêter les carrousels et les sliders, désactiver les effets skeleton et remplacer le spinner par un indicateur statique.
/* Animations de base (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 : désactiver tout */
@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; }
}Dans l'exemple de CSS, un reset global de l'animation est utilisé pour prefers-reduced-motion : reduce : toutes les animations et transitions reçoivent une durée de 0,01 ms et iteration-count 1. Le spinner (bordure statique), le skeleton (fond gris sans scintillement), le parallaxe (désactivé) et le carrousel (scroll-behavior : auto au lieu de smooth) sont redéfinis séparément. Le sélecteur universel * est une sécurité pour tous les éléments.
Pour JavaScript, matchMedia('(prefers-reduced-motion: reduce)').matches est disponible. Si c'est true — n'exécutez pas d'animations via requestAnimationFrame, setInterval ou la Web Animations API. Exemple : un slider avec reduceMotion ne tourne pas automatiquement, uniquement via les boutons. Des bibliothèques comme GSAP, Framer Motion et Anime.js prennent en charge cette vérification via leurs options d'accessibilité.
WCAG 2.2 (2023) a introduit un nouveau critère 2.3.3 Animation from Interactions (niveau AAA) : si une animation est déclenchée par une interaction de l'utilisateur (clic, défilement, survol), elle doit pouvoir être désactivée ou ne pas dépasser 5 secondes. L'animation non liée à une interaction (spinner de chargement, barre de progression) ne relève pas de ce critère. Pour le niveau AA, il suffit que l'animation ne soit pas le seul moyen de transmettre l'information.
Le critère 2.3.3 a été ajouté après de nombreuses plaintes concernant le mal des transports provoqué par le parallaxe au défilement et l'animation « pull-to-refresh ». W3C recommande à tous les sites et applications : ne pas animer les éléments plus de 5 secondes, fournir un commutateur de désactivation de l'animation (via un panneau de contrôle ou prefers-reduced-motion) et ne pas utiliser d'éléments pulsants ou clignotants (dangereux pour l'épilepsie).
Pour respecter WCAG 2.2, un développeur doit : vérifier prefers-reduced-motion et désactiver l'animation lorsque le réglage est actif, fixer une durée maximale d'animation de 5 secondes (si l'animation ne peut pas être désactivée), fournir un commutateur UI d'animation dans les réglages de l'application, ne pas utiliser les effets de parallaxe comme seul moyen de navigation et tester avec Reduce Motion activé dans tous les navigateurs et sur tous les appareils.
Pour tester le comportement de l'application avec Reduce Motion, utilisez : iOS Simulator (activer Reduce Motion dans Settings > Accessibility), Android Emulator (activer « Supprimer les animations »), Chrome DevTools (Rendering > Emulate CSS media feature prefers-reduced-motion) et l'inspecteur web de Safari (activer Reduce Motion dans les Préférences Système macOS > Accessibilité > Affichage). Vérifiez que le contenu reste accessible et lisible sans animation.
Questions fréquentes
Reduce Motion — une fonction d'accessibilité du système d'exploitation qui désactive l'animation de l'interface (parallaxe, transitions, mise à l'échelle des icônes) pour les personnes souffrant de troubles vestibulaires. Elle s'active dans Settings > Accessibility. Le système transmet le signal aux applications via UIAccessibility (iOS), Settings.Global (Android) ou prefers-reduced-motion (CSS), et le développeur peut adapter l'animation.
Sur un iPhone, Reduce Motion s'active dans Settings > Accessibility > Motion > Reduce Motion. Une fois activé, le parallaxe du fond d'écran, les effets iMessage, l'animation d'ouverture des applications et les transitions entre les écrans sont désactivés (remplacés par un cross-fade). Les animations système d'UIKit ne sont pas lues. Le réglage s'applique à toutes les applications sans redémarrer l'appareil.
Sur Android, l'animation se désactive de deux manières : Settings > Accessibility > Supprimer les animations (recommandé pour les utilisateurs) ou Options développeur > Échelle d'animation — la désactiver. La méthode d'accessibilité garantit que toutes les applications reçoivent le signal. Les Options développeur n'affectent que les animations système et peuvent être masquées sur certains appareils.
La media feature CSS prefers-reduced-motion : reduce permet de désactiver l'animation au niveau des styles. Il est recommandé de définir un reset universel : animation-duration : 0,01 ms, transition-duration : 0,01 ms, animation-iteration-count : 1 pour tous les éléments. Redéfinissez séparément les composants spécifiques (spinner, skeleton, parallaxe). JavaScript est vérifié via matchMedia('(prefers-reduced-motion: reduce)').
WCAG 2.2 le critère 2.3.3 (AAA) exige que l'animation déclenchée par une interaction de l'utilisateur soit désactivable ou ne dépasse pas 5 secondes. Pour AA, il suffit que l'animation ne soit pas le seul moyen de transmettre l'information. Il est recommandé de toujours vérifier prefers-reduced-motion et de fournir un commutateur UI d'animation dans les réglages de l'application.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.