Respecter les préférences de mouvement des utilisateurs
Publié: 2022-03-10prefers-reduced-motion
préféré est parfaitement prise en charge dans tous les navigateurs modernes depuis quelques années. Dans cet article, Michelle Barker explique pourquoi il n'y a aucune raison de ne pas l'utiliser aujourd'hui pour rendre vos sites plus accessibles.Lorsque vous travaillez avec le mouvement sur le Web, il est important de considérer que tout le monde ne le vit pas de la même manière. Ce qui peut sembler lisse et lisse pour certains peut être ennuyeux ou gênant pour d'autres - ou pire, induire des sentiments de malaise ou même provoquer des crises. Les sites Web avec beaucoup de mouvement peuvent également avoir un impact plus important sur la durée de vie de la batterie des appareils mobiles ou entraîner l'utilisation de plus de données (la lecture automatique de vidéos, par exemple, nécessitera plus de données d'un utilisateur qu'une image statique). Ce ne sont là que quelques-unes des raisons pour lesquelles les sites à fort mouvement peuvent ne pas être souhaitables pour tous.
La plupart des nouveaux systèmes d'exploitation permettent à l'utilisateur de définir ses préférences de mouvement dans ses paramètres au niveau du système. La prefers-reduced-motion
préférés (qui fait partie de la spécification des requêtes multimédias de niveau 5) nous permet de détecter les préférences de mouvement des utilisateurs au niveau du système et d'appliquer des styles CSS qui respectent cela.
Les deux options pour prefers-reduced-motion
sont reduce
ou no-preference
. Nous pouvons l'utiliser de la manière suivante dans notre CSS pour désactiver l'animation d'un élément si l'utilisateur a explicitement défini une préférence pour le mouvement réduit :
.some-element { animation: bounce 1200ms; } @media (prefers-reduced-motion: reduce) { .some-element { animation: none; } }
Inversement, nous pourrions définir l'animation uniquement si l'utilisateur n'a aucune préférence de mouvement. Cela a l'avantage de réduire la quantité de code que nous devons écrire, et signifie qu'il est moins probable que nous oublions de répondre aux préférences de mouvement des utilisateurs :
@media (prefers-reduced-motion: no-preference) { .some-element { animation: bounce 1200ms; } }
Un avantage supplémentaire est que les anciens navigateurs qui ne prennent pas en charge les prefers-reduced-motion
ignoreront la règle et n'afficheront que notre élément d'origine sans mouvement.
Quelle règle ?
Contrairement aux requêtes média min-width
et max-width
, où le consensus plus ou moins établi est mobile-first (favorisant donc min-width
), il n'y a pas une seule "bonne" façon d'écrire vos styles de mouvement réduit. J'ai tendance à privilégier le deuxième exemple (appliquer des animations uniquement si prefers-reduced-motion: no-preference
évalue vrai), pour les raisons énumérées ci-dessus. Tatiana Mac a écrit cet excellent article qui couvre certaines des approches que les développeurs pourraient envisager d'adopter, ainsi que de nombreux autres points intéressants, y compris les questions clés à poser lors de la conception avec mouvement sur le Web.
Comme toujours, la communication d'équipe et une stratégie cohérente sont essentielles pour garantir que toutes les bases sont couvertes en matière d'accessibilité Web.
Utilisation pratique : appliquer prefers-reduced-motion
au comportement de défilement
prefers-reduced-motion
a de nombreuses applications au-delà de l'application (ou de la non-application) d'animations ou de transitions d'images clés. Un exemple est le défilement fluide. Si nous définissons scroll-behaviour: smooth
sur notre élément html
, lorsqu'un utilisateur clique sur un lien d'ancrage dans la page, il défilera en douceur jusqu'à la position appropriée sur la page ( actuellement non pris en charge dans Safari ) :
html { scroll-behavior: smooth; }
Malheureusement, en CSS, nous n'avons pas beaucoup de contrôle sur ce comportement pour le moment. Si nous avons une longue page de contenu, la page défile très rapidement, ce qui peut être une expérience assez désagréable pour une personne sensible au mouvement. En l'enveloppant dans une requête multimédia, nous pouvons empêcher l'application de ce comportement dans les cas où l'utilisateur a une préférence reduced-motion
:
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
Restauration des préférences de mouvement en Javascript
Parfois, nous devons appliquer le mouvement en JavaScript plutôt qu'en CSS. Nous pouvons également détecter les préférences de mouvement d'un utilisateur avec JS, en utilisant matchMedia
. Voyons comment nous pouvons conditionnellement implémenter un comportement de défilement fluide dans notre code JS :
/* Set the media query */ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)') button.addEventListener('click', () => { /* If the media query matches, set scroll behavior variable to 'auto', otherwise set it to 'smooth' */ const behavior = prefersReducedMotion.matches ? 'auto' : 'smooth' /* When the button is clicked, the user will be scrolled to the top */ window.scrollTo({ x: 0, y: 0, behavior }) })
Le même principe peut être utilisé pour détecter s'il faut implémenter des interfaces utilisateur riches en mouvement avec des bibliothèques JS - ou même s'il faut charger les bibliothèques elles-mêmes.
Dans l'extrait de code suivant, la fonction revient tôt si l'utilisateur préfère un mouvement réduit, évitant l'importation inutile d'une grande dépendance - un gain de performances pour l'utilisateur. Si aucune préférence de mouvement n'est définie, nous pouvons importer dynamiquement la bibliothèque d'animations Greensock et initialiser nos animations.
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)') const loadGSAPAndInitAnimations = () => { /* If user prefers reduced motion, do nothing */ if (prefersReducedMotion.matches) return /* Otherwise, import the GSAP module and initialize animations */ import('gsap').then((object) => { const gsap = object.default /* Initialize animations with GSAP here */ }) } loadGSAPAndInitAnimations()
reduced-motion
ne signifie pas qu'il n'y a pas de mouvement
Lors du style pour les préférences de mouvement réduit, il est important que nous fournissions toujours à l'utilisateur des indicateurs significatifs et accessibles du moment où une action s'est produite. Par exemple, lors de la désactivation d'un état de survol distrayant ou à forte intensité de mouvement pour les utilisateurs qui préfèrent un mouvement réduit, nous devons veiller à fournir un style alternatif clair lorsque l'utilisateur survole l'élément.
La démo suivante montre une transition élaborée lorsque l'utilisateur survole ou se concentre sur un élément de la galerie s'il n'a pas défini de préférence de mouvement. S'ils préfèrent un mouvement réduit, la transition est plus subtile, mais indique toujours clairement l'état de survol :
Un mouvement réduit ne signifie pas nécessairement non plus la suppression de toutes les transformations de notre page Web. Par exemple, un bouton avec une petite icône en forme de flèche qui se déplace de quelques pixels au survol est peu susceptible de causer des problèmes à quelqu'un qui préfère une expérience de mouvement réduit et fournit un indicateur plus utile d' un changement d'état que la couleur seule.
Je vois parfois des développeurs appliquer des styles de mouvement réduits de la manière suivante, ce qui élimine toutes les transitions et animations sur tous les éléments :
@media screen and (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto !important; } }
C'est sans doute mieux que d'ignorer les préférences de mouvement des utilisateurs, mais cela ne nous permet pas d'adapter facilement les éléments pour fournir des transitions plus subtiles si nécessaire.
Dans l'extrait de code suivant, nous avons un bouton qui s'agrandit au survol . Nous changeons les couleurs et l'échelle, mais les utilisateurs qui préfèrent le mouvement réduit n'obtiendront aucune transition :
button { background-color: hotpink; transition: color 300ms, background-color 300ms, transform 500ms cubic-bezier(.44, .23, .47, 1.27); } button:hover, button:focus { background-color: darkviolet; color: white; transform: scale(1.2); } @media screen and (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto !important; } button { /* Even though we would still like to transition the colors of our button, the following rule will have no effect */ transition: color 200ms, background-color 200ms; } button:hover, button:focus { /* Preventing the button scaling on hover */ transform: scale(1); } }
Découvrez cette démo pour voir l'effet. Ce n'est peut-être pas idéal, car le changement de couleur soudain sans transition peut sembler plus choquant qu'une transition de quelques centaines de millisecondes. C'est l'une des raisons pour lesquelles, dans l'ensemble, je préfère généralement le style pour un mouvement réduit au cas par cas.
Si vous êtes intéressé, il s'agit de la même démo remaniée pour permettre de personnaliser la transition si nécessaire. Il utilise une propriété personnalisée pour la durée de la transition, ce qui nous permet d'activer et de désactiver la transition d'échelle sans avoir à réécrire toute la déclaration.
Lorsque la suppression de l'animation est meilleure
Eric Bailey soulève le point que "tous les appareils qui peuvent accéder au Web ne peuvent pas également restituer l'animation, ou restituer l'animation en douceur" dans son article, "Revisiter les préférences de mouvement réduit, la requête multimédia à mouvement réduit". Pour les appareils avec un faible taux de rafraîchissement, ce qui peut provoquer des animations saccadées, il peut en fait être préférable de supprimer l'animation . La fonctionnalité de média de update
à jour peut être utilisée pour déterminer ceci :
@media screen and (prefers-reduced-motion: reduce), (update: slow) { * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } }
Assurez-vous de lire l'article complet pour les recommandations d'Eric, car il est une personne de premier ordre à suivre dans le domaine de l'accessibilité.
La somme de toutes les parties
Il est important de garder à l'esprit la conception globale de la page lorsque vous vous concentrez si étroitement sur le CSS au niveau des composants. Ce qui peut sembler une animation assez anodine au niveau du composant peut avoir un impact beaucoup plus important lorsqu'elle est répétée tout au long de la page, et est l'une des nombreuses pièces mobiles.
Dans l'article de Tatiana, elle suggère d'organiser les animations (avec prefers-reduced-motion
) dans un seul fichier CSS, qui ne peut être chargé que si (prefers-reduced-motion: no-preference)
vaut true. Voir la somme totale de toutes nos animations pourrait avoir l'avantage supplémentaire de nous aider à visualiser l'expérience de la visite du site dans son ensemble et à adapter nos styles de mouvement réduit en conséquence.
Basculement de mouvement explicite
Bien que prefers-reduced-motion
soient utiles, elles présentent l'inconvénient de ne s'adresser qu'aux utilisateurs qui connaissent la fonctionnalité dans leurs paramètres système. De nombreux utilisateurs ne connaissent pas ce paramètre, tandis que d'autres utilisent peut-être un ordinateur emprunté, sans accès aux paramètres au niveau du système. Pourtant, d'autres pourraient être satisfaits du mouvement pour la grande majorité des sites, mais trouver des sites avec une utilisation intensive du mouvement difficiles à supporter.
Il peut être ennuyeux de devoir ajuster les préférences de votre système juste pour visiter un site. Pour ces raisons, dans certains cas, il peut être préférable de fournir un contrôle explicite sur le site lui-même pour activer et désactiver le mouvement . Nous pouvons implémenter cela avec JS.
La démo suivante a plusieurs cercles dérivant autour de l'arrière-plan. Les styles d'animation initiaux sont déterminés par les préférences système de l'utilisateur (avec prefers-reduced-motion
), cependant, l'utilisateur a la possibilité d'activer ou de désactiver le mouvement via un bouton. Cela ajoute une classe au body
, que nous pouvons utiliser pour définir des styles en fonction de la préférence sélectionnée. En prime, le choix de la préférence de mouvement est également conservé dans le stockage local - il est donc "mémorisé" lors de la prochaine visite de l'utilisateur.
Propriétés personnalisées
Une fonctionnalité de la démo est que la bascule définit une propriété personnalisée, --playState
, que nous pouvons utiliser pour lire ou mettre en pause des animations. Cela peut être particulièrement pratique si vous devez mettre en pause ou lire plusieurs animations à la fois. Tout d'abord, nous définissons l'état de lecture sur paused
:
.circle { animation-play-state: var(--playState, paused); }
Si l'utilisateur a défini une préférence pour le mouvement réduit dans ses paramètres système, nous pouvons définir l'état de lecture sur running
:
@media (prefers-reduced-motion: no-preference) { body { --playState: running; } }
Remarque : Définir ceci sur le body
, par opposition à l'élément individuel, signifie que la propriété personnalisée peut être héritée.
Lorsque l'utilisateur clique sur la bascule, la propriété personnalisée est mise à jour sur le body
, ce qui bascule toutes les instances où elle est utilisée :
// This will pause all animations that use the `--playState` custom property document.body.style.setProperty('--playState', 'paused')
Ce n'est peut-être pas la solution idéale dans tous les cas, mais l'un des avantages est que l' animation s'arrête simplement lorsque l'utilisateur clique sur la bascule, plutôt que de revenir à son état initial, ce qui pourrait être assez choquant.
Un merci spécial à Scott O'Hara pour ses recommandations visant à améliorer l'accessibilité de la bascule. Il m'a fait prendre conscience que certains lecteurs d'écran n'annoncent pas le texte du bouton mis à jour, qui est modifié lorsqu'un utilisateur clique sur le bouton, et a suggéré role="switch"
sur le bouton à la place, avec aria-checked
on
ou off
au clic.
Composant vidéo
Dans certains cas, basculer le mouvement au niveau du composant peut être une meilleure option. Prenez une page Web avec un arrière-plan vidéo à lecture automatique. Nous devons nous assurer que la vidéo ne se lance pas automatiquement pour les utilisateurs qui préfèrent un mouvement réduit, mais nous devons toujours leur fournir un moyen de lire la vidéo uniquement s'ils le souhaitent . (Certains diront que nous devrions éviter la lecture automatique des vidéos, mais nous ne gagnons pas toujours cette bataille !) mettre la vidéo en pause.
Cette démo montre comment nous pouvons définir l'attribut de lecture automatique lorsque l'utilisateur n'a pas de préférence de mouvement déclarée, en implémentant un bouton de lecture/pause personnalisé pour lui permettre également de basculer la lecture, quelle que soit sa préférence :
(Je suis ensuite tombé sur ce post de Scott O'Hara, détaillant ce cas d'utilisation exact.)
Utilisation de l'élément <picture>
Chris Coyier a écrit un article intéressant combinant quelques techniques pour charger différentes sources multimédias en fonction des préférences de mouvement de l'utilisateur. C'est plutôt cool, car cela signifie que pour les utilisateurs qui préfèrent le mouvement réduit , le fichier GIF beaucoup plus volumineux ne sera même pas téléchargé. L'inconvénient, pour autant que je sache, est qu'une fois le fichier téléchargé, l'utilisateur n'a aucun moyen de revenir à l'alternative sans mouvement.
Je crée une version modifiée de la démo qui ajoute cette option. (Activez le reduced-motion
dans les préférences de votre système pour le voir en action.) Malheureusement, lorsque vous basculez entre les options animées et sans mouvement dans Chrome, il semble que le fichier GIF soit téléchargé à chaque fois, ce qui n'est pas le cas dans d'autres navigateurs:
Pourtant, cette technique semble être une manière plus respectueuse d'afficher les GIF, ce qui peut être une source de frustration pour les utilisateurs.
Prise en charge du navigateur et réflexions finales
prefers-reduced-motion
a un excellent support dans tous les navigateurs modernes depuis quelques années. Comme nous l'avons vu, en adoptant une approche de mouvement réduit d'abord, les navigateurs non compatibles obtiendront simplement un repli reduced-motion
. Il n'y a aucune raison de ne pas l'utiliser aujourd'hui pour rendre vos sites plus accessibles.
Les bascules personnalisées ont certainement leur place et peuvent considérablement améliorer l'expérience des utilisateurs qui ne connaissent pas ce paramètre ou ce qu'il fait. L'inconvénient pour l'utilisateur est l'incohérence - si chaque développeur est obligé de proposer sa propre solution, l'utilisateur doit rechercher une bascule de mouvement à un endroit différent sur chaque site Web.
On dirait que la couche manquante ici est celle des navigateurs . J'aimerais voir les navigateurs implémenter des bascules reduced-motion
, à un endroit facilement accessible à l'utilisateur, afin que les gens sachent où le trouver quel que soit le site sur lequel ils naviguent. Cela pourrait également encourager les développeurs à passer plus de temps à assurer l'accessibilité au mouvement.
Ressources associées
- Spécification des requêtes multimédias de niveau 5, World Wide Web Consortium (W3C)
-
prefers-reduced-motion
, MDN Web Docs, Mozilla - Conception avec mouvement réduit pour les sensibilités au mouvement, Val Head, Smashing Magazine
- Adopter une approche sans mouvement en premier pour les animations, Tatiana Mac
- Technique de cinéma réduit, Prise 2, Chris Coyier, CSS-Tricks
- Revisiting
prefers-reduced-motion
, The Reduced Motion Media Query, Eric Bailey, CSS-Tricks - Réduire le mouvement pour améliorer l'accessibilité, Lindsey Kopacz