Catégories
Astuces et Design

Caractéristiques des médias d'interaction et leur potentiel (pour des hypothèses incorrectes)

Il s'agit d'une version mise à jour et considérablement élargie de l'article publié à l'origine sur dev.opera en 2015. Cet article faisait référence à la version préliminaire de l'éditeur, le 24 mars 2015, de la spécification Media Queries Level 4, et contenait un assez grand malentendu sur la façon dont any-hover:none finirait par être évalué par les navigateurs dans la pratique.

La spécification a depuis été mise à jour (y compris les clarifications et exemples que j'ai soumis suite à la publication de l'article original), donc cette version mise à jour supprime les informations incorrectes de l'original et met les explications en conformité avec le projet de travail le plus récent. Il couvre également des aspects supplémentaires relatifs à la détection tactile / d'entrée JavaScript.

Fonctionnalités des médias d'interaction de niveau 4 pour les requêtes multimédias – pointer, hover, any-pointer et any-hover – sont destinés à permettre aux sites d'implémenter différents styles et fonctionnalités (soit une interactivité spécifique CSS comme :hover, ou comportements JavaScript, lors d'une requête à l'aide de window.matchMedia), en fonction des caractéristiques particulières des périphériques d'entrée d'un utilisateur.

Bien que la spécification soit encore en cours de rédaction, les fonctionnalités des médias d'interaction sont généralement bien prises en charge, bien qu'à ce jour, il existe encore des problèmes et des incohérences dans les différentes implémentations de navigateur – voir le récent pointer/hover/any-pointer/any-hover les résultats des tests, avec des références aux bogues pertinents du navigateur.

Les cas d'utilisation courants cités pour les fonctionnalités de médias d'interaction sont souvent «agrandissez / réduisez les contrôles selon que l'utilisateur dispose d'un appareil à écran tactile ou utilise une souris / un stylet» et «n'utilisez un menu déroulant CSS que si l'utilisateur dispose d'une entrée permettant le survol des interactions basées sur la technologie. »

@media (pointer: fine) {
  /* using a mouse or stylus - ok to use small buttons/controls */
}
@media (pointer: coarse) {
  /* using touch - make buttons and other "touch targets" bigger */
}
@media (hover: hover) {
  /* ok to use :hover-based menus */
}
@media (hover: none) {
  /* don't use :hover-based menus */
}

Il existe également des exemples de développeurs utilisant ces nouvelles fonctionnalités de média d'interaction comme moyen de réaliser une «détection tactile» normalisée, souvent juste pour écouter des événements tactiles lorsque l'appareil est identifié comme ayant un pointeur grossier.

if (window.matchMedia && window.matchMedia("(pointer:coarse)").matches) {
  /* if the pointer is coarse, listen to touch events */
  target.addEventListener("touchstart", ...);
  // ...
} else {
  /* otherwise, listen to mouse and keyboard events */
  // ...
}

Cependant, ces approches sont un peu naïves et découlent d'un malentendu sur ce que ces requêtes de médias d'interaction sont censées nous dire.

Quel est le primaire contribution?

L'une des limites de pointer et hover est que, de par leur conception, ils n'exposent que les caractéristiques de ce qu'un navigateur considère primaire entrée du pointeur. Ce que pense le navigateur, et ce qu'un utilisateur utilise réellement comme entrée principale, peut différer – en particulier maintenant que les lignes entre les périphériques et les types d'entrées qu'ils prennent en charge deviennent de plus en plus flous.

Microsoft Surface avec un clavier, un trackpad, une souris Bluetooth externe, un écran tactile.
Laquelle est l’entrée «principale»? la réponse peut dépendre de l'activité.

Dès la sortie de la porte, il convient de noter que fonctionnalités de média d'interaction ne couvrent que les entrées du pointeur (souris, stylet, écran tactile). Ils ne fournissent aucun moyen de détecter si un utilisateur primaire l'entrée est un clavier ou une interface de type clavier, telle qu'une commande de commutation. En théorie, pour un utilisateur de clavier, un navigateur pourrait rapport pointer: none, signalant que l'entrée principale de l'utilisateur n'est pas du tout un pointeur. Cependant, en pratique, aucun navigateur ne permet aux utilisateurs de spécifier qu'ils sont en fait des utilisateurs de clavier. Gardez donc à l'esprit que, quel que soit le résultat des requêtes sur les fonctionnalités d'interaction multimédia, il vaut la peine de vous assurer que votre site ou votre application fonctionne également pour les utilisateurs de clavier.

Traditionnellement, on pourrait dire que l’entrée principale d’un téléphone ou d’une tablette est l’écran tactile. Cependant, même sur ces appareils, un utilisateur peut avoir une entrée supplémentaire, comme une souris Bluetooth jumelée (une fonctionnalité qui est disponible depuis des années sur Android, est maintenant prise en charge dans iPadOS, et atterrira certainement dans iOS), qu'il utilise comme leur principale entrée.

Un téléphone Android avec un clavier et une souris Bluetooth jumelés, avec l'écran affichant un pointeur de souris réel et un menu contextuel de clic droit dans Chrome
Un iPad avec un clavier, une souris et un Apple Pencil Bluetooth couplés, l'écran affichant le «point» de la souris et le menu contextuel du clic droit dans Safari

Dans ce cas, alors que l'appareil a nominalement pointer: coarse et hover: none, les utilisateurs peuvent en fait utiliser un périphérique pointeur fin capable de survoler. De même, si un utilisateur possède un stylet (comme l'Apple Pencil), son entrée principale peut toujours être signalée comme l'écran tactile, mais plutôt que pointer: coarse, ils ont maintenant une entrée qui peut fournir une précision fine du pointeur.

Dans ces scénarios particuliers, si le site ne fait que agrandir les boutons et les commandes et éviter les interactions basées sur le survol, ce ne serait pas un problème majeur pour l'utilisateur: malgré l'utilisation d'une souris fine et capable de survoler, ou une amende mais quand même pas de stylet capable de survoler, ils obtiendront un style et des fonctionnalités destinés à l'écran tactile grossier et non capable de survoler.

Si le site utilise les indices de pointer: coarse pour des changements plus drastiques, comme écouter uniquement les événements tactiles, alors que volonté être problématique pour les utilisateurs – voir la section sur des hypothèses incorrectes qui peuvent complètement briser l'expérience.

Cependant, considérez le contraire: un ordinateur de bureau ou un ordinateur portable «ordinaire» avec un écran tactile, comme Microsoft Surface. Dans la plupart des cas, l'entrée principale sera le trackpad / souris – avec pointer:fine et hover:hover – mais l'utilisateur peut très bien utiliser l'écran tactile, qui a une précision de pointeur approximative et n'a pas de capacité de survol. Si le style et la fonctionnalité sont ensuite spécifiquement conçus pour s'appuyer sur les caractéristiques du trackpad / souris, l'utilisateur peut trouver problématique ou impossible d'utiliser l'écran tactile grossier, non capable de survoler.

Fonctionnalité Écran tactile Écran tactile + souris Bureau / ordinateur portable Bureau / ordinateur portable + écran tactile
pointer:coarse vrai vrai faux faux
pointer:fine faux faux vrai vrai
hover:none vrai vrai faux faux
hover:hover faux faux vrai vrai

Pour une analyse similaire de ce problème, voir «Le bon et le mauvais des requêtes multimédias de niveau 4» par Stu Cox. Bien qu'il se réfère à une itération encore plus ancienne de la spécification qui ne contenait que pointer et hover et une exigence pour ces fonctionnalités de signaler le le moins capable, plûtot que le primaire, dispositif d'entrée.

Le problème avec l'original pointer et hover à eux seuls, c'est qu'ils ne tiennent pas compte des scénarios à entrées multiples et qu'ils comptent sur le navigateur pour pouvoir choisir correctement un seul primaire contribution. C'est là que any-pointer et any-hover entrer en jeu.

Tester les capacités de toutes les entrées

Au lieu de se concentrer uniquement sur le primaire entrée de pointeur, any-pointer et any-hover signaler les capacités combinées de tout entrées de pointeur disponibles.

Afin de prendre en charge les scénarios à entrées multiples, où différentes entrées (basées sur des pointeurs) peuvent avoir des caractéristiques différentes, plusieurs des valeurs pour any-pointer (et, théoriquement, any-hover, mais cet aspect est inutile comme nous le verrons plus tard) peut correspondre, si différents périphériques d’entrée ont des caractéristiques différentes: l’entrée du pointeur primaire). Dans les implémentations actuelles, ces fonctionnalités multimédias s'évaluent généralement comme suit:

Fonctionnalité Écran tactile Écran tactile + souris Bureau / ordinateur portable Bureau / ordinateur portable + écran tactile
any-pointer:coarse vrai vrai faux vrai
any-pointer:fine faux vrai vrai vrai
any-hover:none faux faux faux faux
any-hover:hover faux vrai vrai vrai
Comparaison de Firefox sur les résultats des requêtes multimédias d'Android avec uniquement l'écran tactile et lors de l'ajout d'une souris Bluetooth. Notez comment pointer et hover restent les mêmes, mais any-pointer et any-hover changer pour couvrir la nouvelle entrée fine capable de survoler.

Pour revenir aux cas d'utilisation d'origine des fonctionnalités de média d'interaction, au lieu de baser notre décision de fournir des entrées plus ou moins grandes ou d'activer la fonctionnalité basée sur le survol uniquement sur les caractéristiques du primaire pointeur, nous pouvons prendre cette décision en fonction des caractéristiques de tout entrées de pointeur disponibles. À peu près traduit, au lieu de dire «agrandissez tous les contrôles si l'entrée principale a pointer: coarse»Ou« ne propose un menu CSS que si l'entrée principale a hover: hover», Nous pouvons créer des requêtes multimédias équivalant à dire« si l’une des entrées du pointeur est coarse, agrandissez les commandes »et« n'offrez un menu de survol que si au moins une des entrées de pointeur disponibles pour l'utilisateur est capable de survoler. »

@media (any-pointer: coarse) {
  /* at least one of the pointer inputs
    is coarse, best to make buttons and 
    other "touch targets" bigger (using 
    the query "defensively" to target 
    the least capable input) */
}
@media (any-hover: hover) {
  /* at least one of the inputs is 
     hover-capable, so it's at least 
     possible for users to trigger
     hover-based menus */
}

En raison de la façon dont any-pointer et any-hover sont actuellement définis (comme «l'union des capacités de tous les dispositifs de pointage disponibles pour l'utilisateur»), any-pointer: none n'évaluera jamais à vrai que s'il y a non entrées de pointeur disponibles et, plus important encore, any-hover: none ne sera jamais vrai que si aucun des entrées de pointeur présentes sont capables de survoler. En particulier pour ces derniers, il n’est donc pas possible d’utiliser le any-hover: none requête pour déterminer si une ou plusieurs entrées de pointeur présentes ne sont pas capables de survoler – nous ne pouvons utiliser cette requête de fonctionnalité multimédia que pour déterminer si oui ou non tout les entrées ne sont pas capables de survoler, ce qui peut tout aussi bien être obtenu en vérifiant si any-hover: hover donne la valeur false. Cela rend le any-hover: none requête essentiellement redondante.

nous pourrait contourner ce problème en déduisant que si any-pointer: coarse est vrai, il s'agit probablement d'un écran tactile, et généralement ces entrées ne sont pas capables de survoler, mais conceptuellement, nous faisons des hypothèses ici, et au moment où il y a un pointeur grossier qui est également capable de survoler, cette logique s'effondre. (Et pour ceux qui doutent que nous puissions jamais voir un écran tactile avec le survol, rappelez-vous que certains appareils, comme le Samsung Galaxy Note et le Surface de Microsoft, ont un stylet capable de survoler qui est détecté même lorsqu'il ne touche pas le numériseur / l'écran, donc certains la forme de détection du «toucher flottant» pourrait ne pas être hors de question à l’avenir.)

Combinaison de requêtes pour des suppositions plus éclairées

Les informations fournies par any-pointer et any-hover peut bien sûr être combiné avec pointer et hover, ainsi que la détermination par le navigateur de ce que primaire l'entrée est capable, pour certaines évaluations légèrement plus nuancées.

@media (pointer: coarse) and (any-pointer: fine) {
  /* the primary input is a touchscreen, but
     there is also a fine input (a mouse or 
     perhaps stylus) present. Make the design
     touch-first, mouse/stylus users can
     still use this just fine (though it may 
     feel a big clunky for them?) */
}
@media (pointer: fine) and (any-pointer: coarse) {
  /* the primary input is a mouse/stylus,
     but there is also a touchscreen 
     present. May be safest to make 
     controls big, just in case users do 
     actually use the touchscreen? */
}
@media (hover: none) and (any-hover: hover) {
  /* the primary input can't hover, but
     the user has at least one other
     input available that would let them
     hover. Do you trust that the primary
     input is in fact what the user is 
     more likely to use, and omit hover-
     based interactions? Or treat hover 
     as as something optional — can be 
     used (e.g. to provide shortcuts) to 
     users that do use the mouse, but 
     don't rely on it? */
}

Changements dynamiques

Selon la spécification, les navigateurs doivent réévaluer les requêtes multimédias en réponse aux modifications de l'environnement utilisateur. Cela signifie que pointer, hover, any-pointer, et any-hover les fonctionnalités des médias d'interaction peuvent changer de manière dynamique à tout moment. Par exemple, l'ajout / la suppression d'une souris Bluetooth sur un appareil mobile / tablette déclenchera un changement de any-pointer / any-hover. Un exemple plus radical serait une tablette Surface, où l'ajout / la suppression de la "protection de type" de l'appareil (qui comprend un clavier et un pavé tactile) entraînera des modifications du primaire entrée elle-même (à partir de pointer: fine / hover: hover lorsque la couverture est présente, pour pointer: coarse / hover: none lorsque la Surface est en «mode tablette»).

Captures d'écran de Firefox sur une tablette Surface. Avec le couvercle attaché, pointer:fine, hover:hover, any-pointer:coarse, any-pointer:fine, et any-hover:hover sont vrais; une fois le capot retiré (et Windows demande si l'utilisateur souhaite passer en «mode tablette»), le toucher devient l'entrée principale avec pointer:coarse et hover:none, et seulement any-pointer:coarse et any-hover:none sont vrai.

Si vous modifiez la mise en page / les fonctionnalités de votre site en fonction de ces fonctionnalités multimédias, sachez que le site peut soudainement changer "sous les pieds de l'utilisateur" chaque fois que les entrées changent, pas seulement lors du premier chargement de la page / du site.

Les requêtes multimédias peuvent ne pas suffire – lancez les scripts

L'inconvénient fondamental des fonctionnalités des médias d'interaction est qu'elles ne nous disent pas nécessairement quoi que ce soit sur les périphériques d'entrée utilisés. maintenant. Pour cela, nous devrons peut-être approfondir les solutions, comme What Input?, Qui gardent une trace des événements JavaScript spécifiques déclenchés. Mais bien sûr, ces solutions ne peuvent nous donner que des informations sur les entrées de l'utilisateur après ils ont déjà commencé à interagir avec le site – à quel point il est peut-être trop tard pour apporter des modifications drastiques à votre mise en page ou à vos fonctionnalités.

Gardez à l'esprit que même ces approches basées sur JavaScript peuvent tout aussi facilement conduire à des résultats incorrects. Cela est particulièrement vrai sur les plates-formes mobiles / tablettes, ou dans les situations où des technologies d'assistance sont impliquées, où il est courant de voir des événements «falsifiés» générés. Par exemple, si nous examinons la série d'événements déclenchés lors de l'activation d'un contrôle sur le bureau à l'aide d'un clavier et d'un lecteur d'écran, nous pouvons voir que de faux événements de souris sont déclenchés. Les technologies d'assistance font cela car, historiquement, une grande partie du contenu Web a été codée pour fonctionner pour les utilisateurs de souris, mais pas nécessairement pour les utilisateurs de clavier, ce qui rend une simulation de ces interactions nécessaire pour certaines fonctionnalités.

De même, lors de l'activation de "Prise en charge complète du clavier" dans Paramètres d'iOS → Accessibilité → Clavier, les utilisateurs peuvent naviguer dans le contenu Web à l'aide d'un clavier Bluetooth externe, comme ils le feraient sur un ordinateur de bureau. Mais si nous examinons la séquence d'événements pour les appareils mobiles / tablettes et le clavier / souris couplé, cette situation produit des événements de pointeur, des événements tactiles et des événements de souris de secours – la même séquence que nous obtiendrions pour une interaction tactile.

Affichage des paramètres iOS avec l'accès complet au clavier activé à gauche et une fenêtre de navigateur iPhone ouverte à droite avec l'outil Quelle entrée.
Lorsqu'il est activé, le paramètre «Accès clavier complet» d'iOS entraîne des événements de pointeur, de toucher et de souris. Quelle entrée? identifie cela comme une entrée tactile

Dans toutes ces situations, des scripts comme What Input? va – naturellement, sans faute de sa part – mal identifier le type d'entrée actuel.

Des hypothèses incorrectes qui peuvent complètement briser l'expérience

Après avoir souligné la complexité des périphériques à entrées multiples, il devrait être clair maintenant que les approches qui n'écoutent que des types d'événements spécifiques, comme la forme de «détection tactile» que nous voyons couramment utilisée, s'effondrent rapidement.

if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) {
  /* if the pointer is coarse, listen to touch events */
  target.addEventListener("touchstart", ...);
  // ...
} else {
  /* otherwise, listen to mouse and keyboard events */
  target.addEventListener("click", ...);
  // ...
}

Dans le cas d'un appareil «tactile» avec des entrées supplémentaires – comme un mobile ou une tablette avec une souris externe – ce code empêchera essentiellement l'utilisateur de pouvoir utiliser autre chose que son écran tactile. Et sur les appareils qui sont principalement pilotés par la souris mais qui ont une interface à écran tactile secondaire – comme un Microsoft Surface – l'utilisateur ne pourra pas utiliser son écran tactile.

Au lieu de penser à cela comme «toucher ou souris / clavier ", sachez qu'il s'agit souvent de" toucher et souris / clavier. » Si nous voulons enregistrer des événements tactiles uniquement lorsqu'il existe un appareil à écran tactile réel pour des raisons de performances, nous pouvons essayer de détecter any-pointer: coarse. Mais nous devrions également garder d'autres écouteurs d'événements réguliers pour la souris et le clavier.

/* always, as a matter of course, listen to mouse and keyboard events */
target.addEventListener("click", ...);
 // ...

if (window.matchMedia && window.matchMedia("(any-pointer: coarse)").matches) {
  /* if there's a coarse pointer, *also* listen to touch events */
  target.addEventListener("touchstart", ...);
  // ...
}

Alternativement, nous pourrions éviter toute cette énigme sur différents types d'événements en utilisant des événements de pointeur, qui couvrent tous les types d'entrées de pointeur dans un modèle d'événement unique et unifié, et sont assez bien pris en charge.

Donnez aux utilisateurs un choix explicite

Une solution potentielle pour contourner parfaitement notre incapacité à déterminer de manière absolue le type d'entrée que les utilisateurs utilisent peut être d'utiliser les informations fournies par les requêtes multimédias et des outils tels que Quelle entrée?, De ne pas basculer immédiatement entre différentes mises en page / fonctionnalités – ou pire. , pour n'écouter que des types d'événements particuliers, et potentiellement verrouiller tous les types d'entrée supplémentaires – mais pour les utiliser uniquement comme signaux pour fournir aux utilisateurs un moyen explicite de changer de mode.

Par exemple, voyez la façon dont Microsoft Office vous permet de basculer entre les modes «tactile» et «souris». Sur les appareils tactiles, cette option est affichée par défaut dans la barre d’outils de l’application, tandis que sur les appareils non tactiles, elle est initialement masquée (bien qu’elle puisse être activée, qu’un écran tactile soit présent ou non).

Capture d'écran de la liste déroulante `` Mode tactile / souris '' de Microsoft Office et comparaison de (une partie de) la barre d'outils telle qu'elle est présentée dans chaque mode

Un site ou une application Web peut adopter la même approche et même définir la valeur par défaut en fonction de primaire l'entrée est – mais permet toujours aux utilisateurs de modifier explicitement les modes. Et, en utilisant une approche similaire à What Input?, Le site pourrait détecter la première apparition d'une entrée tactile et alerter / inviter l'utilisateur s'il souhaite passer à un mode tactile.

Potentiel d'hypothèses incorrectes – interroger de manière responsable

Utilisation de Media Queries Niveau 4 Interaction Media Features et adaptation de nos sites en fonction des caractéristiques des primaire ou une entrée de pointeur supplémentaire est une excellente idée – mais méfiez-vous des fausses hypothèses sur ce que ces fonctionnalités multimédias disent réellement. Comme pour les méthodes de détection de fonctionnalités similaires, les développeurs doivent être conscients de ce qu'ils tentent de détecter exactement, des limites de cette détection particulière et, surtout, de prendre en compte Pourquoi ils le font – d'une manière similaire au problème que j'ai décrit dans mon article sur la détection du toucher.

pointer et hover parlez-nous des capacités de tout ce que le navigateur détermine comme étant l'entrée principale de l'appareil. any-pointer et any-hover vous informent sur les capacités de toutes les entrées connectées, et combinées avec des informations sur l’entrée du pointeur principal, elles nous permettent de faire des suppositions éclairées sur le périphérique / scénario particulier d’un utilisateur. Nous pouvons utiliser ces fonctionnalités pour informer notre mise en page, ou le type d'interaction / fonctionnalité que nous voulons offrir; mais n’écartez pas la possibilité que ces hypothèses soient incorrectes. Les requêtes multimédias elles-mêmes ne sont pas nécessairement défectueuses (bien que le fait que la plupart des navigateurs semblent encore avoir des bizarreries et des bogues ajoute aux problèmes potentiels). Cela dépend simplement de la façon dont ils sont utilisés.

Sur ce, je veux conclure en offrant des suggestions pour vous «défendre» des pièges des détections d'entrée.

Pas

Supposons un seul type d'entrée. Ce n’est pas "toucher ou souris / clavier "ces jours-ci, mais" touchez et souris / clavier »- et les types d'entrée disponibles peuvent changer à tout moment, même après le chargement initial de la page.

Allez-y pointer et hover. l'entrée du pointeur «principal» n'est pas nécessairement celle que vos utilisateurs utilisent.

Compter sur hover en général. Indépendamment de quoi hover ou any-hover suggèrent que vos utilisateurs peuvent avoir une entrée de pointeur qu'ils utilisent actuellement et qui n'est pas compatible avec le survol, et vous ne pouvez actuellement pas la détecter à moins qu'il ne s'agisse de l'entrée principale (car hover: none est vrai si cette une entrée particulière manque de survol, mais any-hover: none ne sera jamais vrai que si aucun des entrées sont capables de survoler). Et n'oubliez pas que les interfaces basées sur le survol ne fonctionnent généralement pas pour les utilisateurs de clavier.

Faire

Rendez vos interfaces «tactiles». Si vous détectez qu'il y a un any-pointer:coarse (probablement un écran tactile), pensez à fournir de grandes cibles tactiles et un espacement suffisant entre elles. Même si l'utilisateur utilise une autre entrée, comme une souris, à ce moment-là, aucun mal n'est fait.

Donnez aux utilisateurs un choix. Si tout le reste échoue, envisagez de donner à l'utilisateur une option / bascule pour basculer entre les dispositions tactiles ou souris. N'hésitez pas à utiliser toutes les informations que vous pouvez glaner à partir des requêtes multimédias (telles que any-pointer: coarse étant vrai) pour faire une estimation éclairée du paramètre initial de la bascule.

Souvenez-vous des utilisateurs de clavier. Indépendamment des entrées de pointeur que l'utilisateur peut ou non utiliser, n'oubliez pas l'accessibilité du clavier – elle ne peut pas être détectée de manière concluante, alors assurez-vous simplement que vos éléments fonctionnent bien sûr pour les utilisateurs de clavier.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *