Aller au contenu
← Tous les articles

Frontend1 min de lecture

Des animations qui respectent prefers-reduced-motion

Réduire le mouvement ne veut pas dire tout couper : une seule source de vérité pour les durées, en CSS comme en JavaScript.

Cercles concentriques bleus qui s’élargissent depuis un point lumineux
Sommaire

Pour certaines personnes, un grand mouvement à l’écran provoque vertiges et nausées. Les systèmes d’exploitation proposent un réglage pour le réduire, que le navigateur expose avec prefers-reduced-motion.

Des durées centralisées

Si chaque composant choisit sa durée, chaque composant doit aussi gérer la préférence. Mieux vaut des variables CSS que l’on écrase une seule fois :

CSS
:root {
  --duration-hover: 250ms;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-hover: 0.01ms;
  }
}

La valeur 0.01ms plutôt que zéro : les événements transitionend continuent d’être émis, et le code qui les attend ne reste pas bloqué.

Et en JavaScript ?

Les animations pilotées par script lisent la même préférence, au même endroit :

TypeScript
const REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)'

export function motionDuration(name: 'hover' | 'snap'): number {
  const reduced = window.matchMedia(REDUCED_MOTION_QUERY).matches
  return reduced ? 0.01 : durations[name]
}

Ce que l’on garde

  • Les fondus courts, qui ne déplacent rien
  • Les changements d’état instantanés (focus, sélection)
  • La barre de progression de lecture, qui suit le défilement sans l’animer
Anneaux concentriques évoquant un indicateur de focus
Un fondu reste lisible là où une translation dérange.
Le mouvement doit servir le récit ; sans lui, le récit doit rester complet.
  • #Accessibilité
  • #Performance

Partager

Un projet, une question ?

Cet article vous a donné une idée, ou vous bloquez sur un problème proche ? Écrivez-moi, je réponds à chaque message.