préfère-réduire-le-mouvement: parfois, il suffit de moins bouger

La requête média prefers-reduced-motion détecte si l'utilisateur a demandé au système d'exploitation de minimiser la quantité d'animations ou de mouvements utilisés.

Tout le monde n'apprécie pas les animations ou les transitions décoratives, et certains utilisateurs souffrent même du mal des transports face au défilement parallaxe, aux effets de zoom, etc. La requête média de préférence utilisateur prefers-reduced-motion vous permet de concevoir une variante de votre site avec moins de mouvements pour les utilisateurs qui ont exprimé cette préférence.

Browser Support

  • Chrome: 74.
  • Edge: 79.
  • Firefox: 63.
  • Safari: 10.1.

Source

Trop de mouvements dans la vie réelle et sur le Web

L'autre jour, je faisais du patin à glace avec mes enfants. Il faisait beau, le soleil brillait et la patinoire était bondée ⛸. Le seul problème, c'est que je ne supporte pas bien la foule. Avec autant de cibles mouvantes, je n'arrive à me concentrer sur rien et je finis par me perdre, avec une sensation de surcharge visuelle totale, presque comme si je fixais une fourmilière 🐜.

Foule de patineurs à glace.
Surcharge visuelle dans la vie réelle.

Il arrive parfois que le Web soit tout aussi déroutant : annonces clignotantes, effets de parallaxe sophistiqués, animations de révélation surprenantes, vidéos en lecture automatique, etc. Le Web peut parfois être assez déroutant… Heureusement, contrairement à la vie réelle, il existe une solution. La requête média CSS prefers-reduced-motion permet aux développeurs de créer une variante d'une page pour les utilisateurs qui préfèrent les animations réduites. Cela peut consister à ne pas utiliser de vidéos en lecture automatique, à désactiver certains effets purement décoratifs ou à repenser complètement une page pour certains utilisateurs.

Avant de me plonger dans la fonctionnalité, revenons un peu en arrière et réfléchissons à l'utilité des animations sur le Web. Si vous le souhaitez, vous pouvez également ignorer les informations générales et passer directement aux détails techniques.

Animation sur le Web

L'animation est souvent utilisée pour fournir un feedback à l'utilisateur, par exemple pour lui indiquer qu'une action a été reçue et est en cours de traitement. Par exemple, sur un site Web de shopping, un produit peut être animé pour "voler" dans un panier virtuel, représenté par une icône en haut à droite du site.

Un autre cas d'utilisation consiste à utiliser le mouvement pour tromper la perception de l'utilisateur en utilisant un mélange d'écrans squelettes, de métadonnées contextuelles et d'aperçus d'images de mauvaise qualité pour occuper une grande partie du temps de l'utilisateur et donner l'impression que l'expérience est plus rapide. L'idée est de donner au client un aperçu de ce qui va arriver et, en attendant, de charger les éléments le plus rapidement possible.

Enfin, il existe des effets décoratifs tels que les dégradés animés, le défilement parallaxe, les vidéos en arrière-plan et bien d'autres. Si de nombreux utilisateurs apprécient ces animations, d'autres les détestent, car ils se sentent distraits ou ralentis par elles. Dans le pire des cas, les utilisateurs peuvent même souffrir du mal des transports comme s'il s'agissait d'une expérience réelle. Pour ces utilisateurs, la réduction des animations est donc une nécessité médicale.

Trouble du spectre vestibulaire déclenché par le mouvement

Certains utilisateurs sont distraits ou nauséeux par le contenu animé. Par exemple, les animations de défilement peuvent provoquer des troubles vestibulaires lorsque des éléments autres que l'élément principal associé au défilement se déplacent beaucoup. Par exemple, les animations de défilement parallaxe peuvent provoquer des troubles vestibulaires, car les éléments d'arrière-plan se déplacent à une vitesse différente de celle des éléments de premier plan. Les réactions liées à un trouble vestibulaire (oreille interne) incluent des vertiges, des nausées et des migraines. Elles nécessitent parfois un repos au lit pour s'en remettre.

Supprimer le mouvement sur les systèmes d'exploitation

De nombreux systèmes d'exploitation proposent depuis longtemps des paramètres d'accessibilité permettant de spécifier une préférence pour la réduction des mouvements. Les captures d'écran suivantes montrent la préférence Réduire les animations de macOS Mojave et la préférence Supprimer les animations d'Android Pie. Lorsque ces préférences sont activées, le système d'exploitation n'utilise pas d'effets décoratifs tels que les animations de lancement d'applications. Les applications elles-mêmes peuvent et doivent également respecter ce paramètre, et supprimer toutes les animations inutiles.

Écran des paramètres macOS avec la case "Réduire les animations" cochée.
Écran des paramètres Android avec la case "Supprimer les animations" cochée.

Supprimer le mouvement sur le Web

Media Queries Level 5 apporte également la préférence utilisateur de mouvement réduit au Web. Les requêtes média permettent aux auteurs de tester et d'interroger les valeurs ou les fonctionnalités de l'agent utilisateur ou de l'appareil d'affichage indépendamment du document affiché. La requête média prefers-reduced-motion est utilisée pour détecter si l'utilisateur a défini une préférence du système d'exploitation afin de minimiser la quantité d'animations ou de mouvements utilisés. Il peut prendre deux valeurs possibles :

  • no-preference : indique que l'utilisateur n'a exprimé aucune préférence dans le système d'exploitation sous-jacent. Cette valeur de mot clé est évaluée comme false dans le contexte booléen.
  • reduce : indique que l'utilisateur a défini une préférence de système d'exploitation indiquant que les interfaces doivent minimiser les mouvements ou les animations, de préférence au point où tous les mouvements non essentiels sont supprimés.

Utiliser la requête média dans les contextes CSS et JavaScript

Comme pour toutes les requêtes média, prefers-reduced-motion peut être vérifié à partir d'un contexte CSS et d'un contexte JavaScript.

Pour illustrer les deux, supposons que j'ai un bouton d'inscription important sur lequel je souhaite que l'utilisateur clique. Je pourrais définir une animation "vibrer" accrocheuse, mais en tant que bon citoyen du Web, je ne la jouerai que pour les utilisateurs qui sont explicitement d'accord avec les animations, mais pas pour tous les autres, qui peuvent être des utilisateurs qui ont désactivé les animations ou des utilisateurs sur des navigateurs qui ne comprennent pas la requête média.

/*
  If the user has expressed their preference for
  reduced motion, then don't use animations on buttons.
*/
@media (prefers-reduced-motion: reduce) {
  button {
    animation: none;
  }
}

/*
  If the browser understands the media query and the user
  explicitly hasn't set a preference, then use animations on buttons.
*/
@media (prefers-reduced-motion: no-preference) {
  button {
    /* `vibrate` keyframes are defined elsewhere */
    animation: vibrate 0.3s linear infinite both;
  }
}

Pour illustrer comment utiliser prefers-reduced-motion avec JavaScript, imaginez que j'ai défini une animation complexe avec l'API Web Animations. Alors que les règles CSS sont déclenchées de manière dynamique par le navigateur lorsque la préférence de l'utilisateur change, pour les animations JavaScript, je dois écouter moi-même les changements, puis arrêter manuellement mes animations potentiellement en cours (ou les redémarrer si l'utilisateur me le permet) :

const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
mediaQuery.addEventListener('change', () => {
  console.log(mediaQuery.media, mediaQuery.matches);
  // Stop JavaScript-based animations.
});

Notez que les parenthèses autour de la requête média proprement dite sont obligatoires :

À éviter
window.matchMedia('prefers-reduced-motion: reduce');
À faire
window.matchMedia('(prefers-reduced-motion: reduce)');

Utiliser la requête média à partir de contextes <picture>

Un cas d'utilisation intéressant consiste à faire dépendre la lecture d'un AVIF, d'un WebP ou d'un GIF animé de l'attribut media. Si (prefers-reduced-motion: no-preference) est évalué à true, vous pouvez afficher la version animée. Sinon, affichez la version statique :

<picture>
  <!-- Animated versions. -->
  <source
    srcset="nyancat.avifs"
    type="image/avif"
    media="(prefers-reduced-motion: no-preference)"
  />
  <source
    srcset="nyancat.gif"
    type="image/gif"
    media="(prefers-reduced-motion: no-preference)"
  />
  <!-- Static versions. -->
  <img src="nyancat.png" alt="Nyan cat" width="250" height="250" />
</picture>

Consultez l'exemple ci-dessous. Essayez d'activer ou de désactiver les préférences de mouvement de votre appareil pour voir la différence.

Le célèbre Nyan Cat.

Découvrir les préférences de l'utilisateur au moment de la requête

L'en-tête d'indication client Sec-CH-Prefers-Reduced-Motion permet aux sites d'obtenir les préférences de mouvement de l'utilisateur de manière facultative au moment de la requête, ce qui permet aux serveurs d'intégrer le bon CSS pour des raisons de performances.

Démo

J'ai créé une petite démo basée sur les incroyables 🐈 chats de statut HTTP de Rogério Vicente. Tout d'abord, prenez le temps d'apprécier la blague, elle est hilarante, je vous attends. Maintenant que vous êtes de retour, laissez-moi vous présenter la démonstration. Lorsque vous faites défiler la page, chaque chat d'état HTTP apparaît alternativement du côté droit ou du côté gauche. Il s'agit d'une animation fluide à 60 FPS, mais comme indiqué précédemment, certains utilisateurs peuvent ne pas l'apprécier, voire avoir le mal des transports. La démo est donc programmée pour respecter prefers-reduced-motion. Cela fonctionne même de manière dynamique. Les utilisateurs peuvent donc modifier leurs préférences à la volée, sans avoir à recharger la page. Si un utilisateur préfère les mouvements réduits, les animations de révélation non nécessaires disparaissent et seul le mouvement de défilement normal reste. La capture d'écran suivante montre la démo en action :

Vidéo de l'application de prefers-reduced-motion démonstration

Conclusions

Le respect des préférences des utilisateurs est essentiel pour les sites Web modernes. Les navigateurs proposent de plus en plus de fonctionnalités pour permettre aux développeurs Web de le faire. Un autre exemple lancé est prefers-color-scheme, qui détecte si l'utilisateur préfère un jeu de couleurs clair ou sombre. Vous trouverez toutes les informations sur prefers-color-scheme dans mon article Hello Darkness, My Old Friend 🌒.

Le groupe de travail CSS standardise davantage de requêtes média de préférences utilisateur, comme prefers-reduced-transparency (détecte si l'utilisateur préfère une transparence réduite), prefers-contrast (détecte si l'utilisateur a demandé au système d'augmenter ou de diminuer le contraste entre les couleurs adjacentes) et inverted-colors (détecte si l'utilisateur préfère les couleurs inversées).

(Bonus) Forcer les mouvements réduits sur tous les sites Web

Certains sites n'utilisent pas prefers-reduced-motion ou pas suffisamment à votre goût. Si, pour quelque raison que ce soit, vous souhaitez arrêter le mouvement sur tous les sites Web, vous pouvez le faire. Pour ce faire, vous pouvez injecter une feuille de style avec le code CSS suivant dans chaque page Web que vous consultez. Il existe plusieurs extensions de navigateur (à utiliser à vos propres risques) qui permettent de le faire.

@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    animation-delay: -1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    background-attachment: initial !important;
    scroll-behavior: auto !important;
    transition-duration: 1ms !important;
    transition-delay: -1ms !important;
  }
}

Pour ce faire, le CSS précédent remplace les durées de toutes les animations et transitions par une durée si courte qu'elles ne sont plus visibles. Comme certains sites Web dépendent de l'exécution d'une animation pour fonctionner correctement (peut-être parce qu'une certaine étape dépend du déclenchement de l'événement animationend), l'approche animation: none !important; plus radicale ne fonctionnerait pas. Même le hack précédent n'est pas garanti de fonctionner sur tous les sites Web (par exemple, il ne peut pas arrêter le mouvement initié à l'aide de l'API Web Animations). Assurez-vous donc de le désactiver lorsque vous remarquez des problèmes.

Ressources

Remerciements

Un grand merci à Stephen McGruer qui a implémenté prefers-reduced-motion dans Chrome et qui, avec Rob Dodson, a également relu ce document.