Características de los medios de interacción y su potencial (en caso de suposiciones incorrectas)
- ¿Cuál es la entrada principal?
- Probar las capacidades de todas las entradas.
- Combinar consultas para obtener conjeturas más fundamentadas
- Cambios dinámicos
- Las consultas de medios pueden no ser suficientes: continúe con las secuencias de comandos
- Suposiciones incorrectas que pueden romper completamente la experiencia.
- Dar a los usuarios una opción explícita
- Potencial de suposiciones incorrectas: consulte de manera responsable
Esta es una versión actualizada y muy ampliada del artículo publicado originalmente en dev.opera en 2015. Ese artículo hacía referencia al borrador del editor del 24 de marzo de 2015 de la determinación Media Queries Level 4 y contenía un malentendido bastante grande sobre cómo any-hover:none
terminaría. siendo evaluado por los navegadores en la práctica.
Desde entonces, la especificación se actualizó (incluidas aclaraciones y ejemplos que envié después de la publicación del artículo original), por lo que esta versión actualizada elimina la información incorrecta del original y alinea las explicaciones con el borrador de trabajo más reciente. También cubre aspectos adicionales relacionados con la detección de entrada/toque de JavaScript.
Las funciones de medios de interacción de nivel 4 de consultas de medios ( pointer
, hover
y any-pointer
) any-hover
están destinadas a permitir que los sitios implementen diferentes estilos y funcionalidades (ya sea interactividad específica de CSS como :hover
o comportamientos de JavaScript, cuando se consulta mediante window.matchMedia
), dependiendo de las características particulares de la entrada de un usuario. dispositivos.
Aunque la especificación aún está en borrador, las funciones de medios de interacción generalmente son bien compatibles, aunque, hasta la fecha, todavía hay algunos problemas e inconsistencias en las diversas implementaciones del navegador; consulte los resultados de las pruebas /// pointer
recientes hover
any-pointer
any-hover
, con referencias a errores relevantes del navegador. .
Los casos de uso comunes citados para las funciones de medios de interacción a menudo son “hacer que los controles sean más grandes o más pequeños dependiendo de si el usuario tiene un dispositivo con pantalla táctil o está usando un mouse o lápiz óptico” y “solo use un menú desplegable CSS si el usuario tiene una entrada que le permite desplazarse”. -interacciones basadas “.
@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 */}
También hay ejemplos de desarrolladores que utilizan estas nuevas funciones de medios de interacción como una forma de lograr una “detección táctil” basada en estándares, a menudo solo para escuchar eventos táctiles cuando se identifica que el dispositivo tiene un puntero grueso.
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 */ // ...}
Sin embargo, estos enfoques son un poco ingenuos y surgen de una mala comprensión de lo que estas consultas de medios de interacción están diseñadas para decirnos.
¿Cuál es la entrada principal?
Una de las limitaciones de pointer
y hover
es que, por diseño, solo exponen las características de lo que un navegador considera la entrada del puntero principal. Lo que piensa el navegador y lo que un usuario utiliza realmente como entrada principal pueden diferir, especialmente ahora que las líneas entre los dispositivos y los tipos de entradas que admiten se están regresando cada vez más borrosas.
Desde el principio, vale la pena señalar que las funciones de medios de interacción solo cubren las entradas del puntero (ratón, lápiz óptico, pantalla táctil). No proporciona ninguna forma de detectar si la entrada principal de un usuario es un teclado o una interfaz similar a un teclado, como un control de interruptor. En teoría, para un usuario de teclado, un navegador podría informar pointer: none
, indicando que la entrada principal del usuario no es un puntero en absoluto. Sin embargo, en la práctica, ningún navegador ofrece una manera para que los usuarios especifiquen que en realidad son usuarios de teclado. Así que tenga en cuenta que, independientemente de lo que puedan devolver las consultas sobre funciones de medios de interacción, vale la pena asegurarse de que su sitio o aplicación también funcione para usuarios de teclado.
Tradicionalmente, podríamos decir que la entrada principal de un teléfono o tableta es la pantalla táctil. Sin embargo, incluso en estos dispositivos, un usuario puede tener una entrada adicional, como un mouse bluetooth emparejado (una función que ha estado disponible durante años en Android, ahora es compatible con iPadOS y seguramente llegará a iOS), que son utilizando como insumo principal.
En este caso, si bien el dispositivo tiene nominalmente pointer: coarse
y hover: none
, es posible que los usuarios en realidad estén usando un dispositivo de puntero fino que es capaz de desplazarse. De manera similar, si un usuario tiene un lápiz óptico (como el Apple Pencil), es posible que su entrada principal aún se informe como la pantalla táctil, pero en lugar de pointer: coarse
, ahora tiene una entrada que puede proporcionar una precisión de puntero fino.
En estos escenarios particulares, si lo único que hace el sitio es agrandar los botones y controles y evitar las interacciones basadas en el desplazamiento, eso no sería un problema importante para el usuario: a pesar de usar un mouse fino y con capacidad de desplazamiento, o un mouse fino pero aún así Sin un lápiz óptico con capacidad para desplazarse, obtendrán un estilo y una funcionalidad dirigidas a la pantalla táctil tosca y sin capacidad para desplazarse.
Si el sitio utiliza las señales de pointer: coarse
para cambios más drásticos, como escuchar solo eventos táctiles, entonces eso será problemático para los usuarios; consulte la sección sobre suposiciones incorrectas que pueden interrumpir por completa la experiencia.
Sin embargo, considere lo contrario: una computadora de escritorio o una computadora portátil “normal” con pantalla táctil, como la Surface de Microsoft. En la mayoría de los casos, la entrada principal será el trackpad/ratón (con pointer:fine
y hover:hover
), pero es posible que el usuario esté usando la pantalla táctil, que tiene una precisión de puntero aproximada y no tiene capacidad de desplazamiento. Si el estilo y la funcionalidad se adaptan específicamente a las características del trackpad/ratón, al usuario puede resultarle problemático o imposible utilizar la pantalla táctil tosca y sin capacidad de desplazamiento.
característica | Pantalla tactil | Pantalla táctil + ratón | Computadora de escritorio/portátil | Computadora de escritorio/portátil + pantalla táctil |
---|---|---|---|---|
pointer:coarse |
verdadero | verdadero | FALSO | FALSO |
pointer:fine |
FALSO | FALSO | verdadero | verdadero |
hover:none |
verdadero | verdadero | FALSO | FALSO |
hover:hover |
FALSO | FALSO | verdadero | verdadero |
Para una visión similar de este problema, consulte “Lo bueno y lo malo de las consultas de medios de nivel 4” de Stu Cox. Si bien se refiere a una iteración aún anterior de la especificación que solo contenía pointer
un hover
requisito para que estas características informaran el dispositivo de entrada menos capaz, en lugar del principal.
El problema con el original pointer
y hover
por sí solo es que no tienen en cuenta escenarios de entradas múltiples y dependen del navegador para poder seleccionar correctamente una única entrada principal. Ahí es donde entra en juego any-pointer
y .any-hover
Probar las capacidades de todas las entradas.
En lugar de centrarse únicamente en la entrada del puntero principal any-pointer
, informe any-hover
las capacidades combinadas de todas las entradas del puntero disponibles.
Para admitir escenarios de múltiples entradas, donde diferentes entradas (basadas en punteros) pueden tener diferentes características, más de uno de los valores para any-pointer
(y, teóricamente, any-hover
pero este aspecto es inútil, como veremos adelante más) puede coincidir. si diferentes dispositivos de entrada tienen características diferentes (en comparación con el puntero y el desplazamiento, que solo se refiere a las capacidades de la entrada del puntero principal). En las implementaciones actuales, estas características multimedia generalmente se evalúan de la siguiente manera:
característica | Pantalla tactil | Pantalla táctil + ratón | Computadora de escritorio/portátil | Computadora de escritorio/portátil + pantalla táctil |
---|---|---|---|---|
any-pointer:coarse |
verdadero | verdadero | FALSO | verdadero |
any-pointer:fine |
FALSO | verdadero | verdadero | verdadero |
any-hover:none |
verdadero | FALSO | FALSO | FALSO |
any-hover:hover |
FALSO | verdadero | verdadero | verdadero |
Volviendo a los casos de uso originales de las funciones de medios de interacción, en lugar de basar nuestra decisión de proporcionar entradas más grandes o más pequeñas o habilitar la funcionalidad basada en el desplazamiento solo en las características de la entrada del puntero principal, podemos tomar esa decisión en función de las características. de cualquier entrada de puntero disponible. Traducido de forma aproximada, en lugar de decir "aumentar todos los controles si la entrada principal tiene pointer: coarse
" o "ofrecer solo un menú CSS si la entrada principal tiene hover: hover
", podemos crear consultas de medios que equivalgan a decir "si alguna de las entradas del puntero es coarse
, hacer los controles más grandes” y “solo ofrecer un menú basado en el desplazamiento si al menos una de las entradas de puntero disponibles para el usuario es compatible con el desplazamiento”.
@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 */}
Debido a la forma en que any-pointer
y any-hover
se definen actualmente (como “la unión de capacidades de todos los dispositivos señaladores disponibles para el usuario”), any-pointer: none
solo se evaluará como verdadero si no hay entradas de puntero disponibles y, lo que es más importante, any-hover: none
solo se evaluará como verdadero. Es verdadero si ninguna de las entradas de puntero presentes es compatible con el desplazamiento. Particularmente para este último, por lo tanto, no es posible usar la any-hover: none
consulta para determinar si solo una o más de las entradas de puntero presentes no son compatibles con el desplazamiento; solo podemos usar esta consulta de función multimedia para determinar si todas las entradas no son compatibles con el desplazamiento. capaz, que es algo que también se puede lograr comprobando si any-hover: hover
se evalúa como falso. Esto hace que la any-hover: none
consulta sea esencialmente redundante.
Podríamos solucionar esto infiriendo que si any-pointer: coarse
es cierto, es probable que sea una pantalla táctil y, en general, esas entradas no son compatibles con el desplazamiento, pero conceptualmente, estamos haciendo suposiciones aquí, y en el momento en que hay un puntero aproximado que también es compatible con el desplazamiento , esa lógica se desmorona. (Y para aquellos que dudan de que alguna vez veamos una pantalla táctil con función de desplazamiento, recuerden que algunos dispositivos, como el Samsung Galaxy Note y el Surface de Microsoft, tienen un lápiz con capacidad de desplazamiento que se detecta incluso cuando no está tocando el digitalizador/pantalla, por lo que algunos (La forma de detección de “toque flotante” puede no estar descartada en el futuro).
Combinar consultas para obtener conjeturas más fundamentadas
La información proporcionada por any-pointer
y, any-hover
por supuesto, se puede combinar con pointer
y hover
, así como la determinación del navegador de lo que la entrada principal es capaz de hacer, para realizar algunas evaluaciones un poco más matizadas.
@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 something optional — can be used (e.g. to provide shortcuts) to users that do use the mouse, but don't rely on it? */}
Cambios dinámicos
Según la especificación, los navegadores deben reevaluar las consultas de medios en respuesta a los cambios en el entorno del usuario. Esto significa que las características de los medios de interacción pointer
, hover
, any-pointer
y any-hover
pueden cambiar dinámicamente en cualquier momento. Por ejemplo, agregar o quitar un mouse bluetooth en un dispositivo móvil o tableta provocará un cambio en any-pointer
/ any-hover
. Un ejemplo más drástico sería una tableta Surface, donde agregar/quitar la “cubierta con teclado” del dispositivo (que incluye un teclado y un trackpad) resultará en cambios en la entrada principal en sí (desde pointer: fine
/ hover: hover
cuando la cubierta está presente, hasta pointer: coarse
/ hover: none
cuando la Surface está en “modo tableta”).
Si está modificando el diseño/funcionalidad de su sitio en función de estas características multimedia, tenga en cuenta que el sitio puede cambiar repentinamente "bajo los pies del usuario" cada vez que cambian las entradas, no solo cuando la página/sitio se carga por primera vez.
Las consultas de medios pueden no ser suficientes: continúe con las secuencias de comandos
La deficiencia fundamental de las características de los medios de interacción es que no necesariamente nos dicen nada sobre los dispositivos de entrada que están en uso en este momento. Para eso, es posible que necesitemos profundizar en soluciones, como What Input?, que realizan un seguimiento de los eventos de JavaScript específicos activados. Pero, por supuesto, esas soluciones sólo pueden brindarnos información sobre los comentarios del usuario después de que ya hayan comenzado a interactuar con el sitio, momento en el cual puede ser demasiado tarde para realizar cambios drásticos en su diseño o funcionalidad.
Tenga en cuenta que incluso estos enfoques basados en JavaScript pueden conducir fácilmente a resultados incorrectos. Esto es especialmente cierto en plataformas móviles/tabletas, o en situaciones donde están involucradas tecnologías de asistencia, donde es común ver que se generan eventos “falsos”. Por ejemplo, si observamos la serie de eventos que se activan al activar un control en el escritorio mediante un teclado y un lector de pantalla, podemos ver que se activan eventos falsos del mouse. Las tecnologías de asistencia hacen esto porque, históricamente, una gran cantidad de contenido web ha sido codificado para funcionar con usuarios de mouse, pero no necesariamente con usuarios de teclado, lo que hace necesaria una simulación de esas interacciones para algunas funcionalidades.
De manera similar, al activar “Compatibilidad total con teclado” en Configuración → Accesibilidad → Teclado de iOS, los usuarios pueden navegar por el contenido web utilizando un teclado bluetooth externo, tal como lo harían en el escritorio. Pero si observamos la secuencia de eventos para dispositivos móviles/tabletas y teclado/ratón emparejados, esa situación produce eventos de puntero, eventos táctiles y eventos de mouse de reserva, la misma secuencia que obtendríamos para una interacción con pantalla táctil.
En todas estas situaciones, guiones como What Input? (comprensiblemente, sin que sea culpa suya) identificará erróneamente el tipo de entrada actual.
Suposiciones incorrectas que pueden romper completamente la experiencia.
Habiendo esbozado la complejidad de los dispositivos de entradas múltiples, a estas alturas debería quedar claro que los enfoques que sólo escuchan tipos específicos de eventos, como la forma de “detección táctil” que vemos comúnmente en uso, rápidamente se desmoronan.
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", ...); // ...}
En el caso de un dispositivo “táctil” con entradas adicionales, como un móvil o una tableta con un mouse externo, este código básicamente evitará que el usuario pueda usar cualquier otra cosa que no sea su pantalla táctil. Y en dispositivos que funcionan principalmente con un mouse pero que tienen una interfaz de pantalla táctil secundaria, como Microsoft Surface, el usuario no podrá usar su pantalla táctil.
En lugar de pensar en esto como "toque o mouse/teclado", tenga en cuenta que a menudo se trata de "toque y mouse/teclado". Si solo queremos registrar eventos táctiles cuando hay un dispositivo con pantalla táctil real por razones de rendimiento, podemos intentar detectarlos any-pointer: coarse
. Pero también deberíamos mantener otros detectores de eventos habituales para el mouse y el teclado.
/* 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", ...); // ...}
Alternativamente, podríamos evitar todo este enigma sobre diferentes tipos de eventos usando eventos de puntero, que cubren todos los tipos de entradas de puntero en un modelo de evento único y unificado y están bastante bien soportados.
Dar a los usuarios una opción explícita
Una posible solución para eludir claramente nuestra incapacidad de tomar determinaciones absolutas sobre qué tipo de entrada están utilizando los usuarios puede ser utilizar la información proporcionada por consultas de medios y herramientas como What Input?, no cambiar inmediatamente entre diferentes diseños/funcionalidades, o algo peor. , para escuchar solo tipos particulares de eventos y potencialmente bloquear cualquier tipo de entrada adicional, pero usarlos solo como señales de cuándo proporcionar a los usuarios una forma explícita de cambiar de modo.
Por ejemplo, vea la forma en que Microsoft Office le permite cambiar entre el modo "táctil" y "ratón". En los dispositivos táctiles, esta opción se muestra de forma predeterminada en la barra de herramientas de la aplicación, mientras que en los dispositivos no táctiles está inicialmente oculta (aunque se puede habilitar, independientemente de si hay una pantalla táctil presente o no).
Un sitio o aplicación web podría adoptar el mismo enfoque e incluso establecer el valor predeterminado en función de cuál sea la entrada principal, pero aún así permitir a los usuarios cambiar los modos explícitamente. Y, utilizando un enfoque similar a What Input?, el sitio podría detectar la primera aparición de una entrada táctil y alertar/avisar al usuario si desea cambiar a un modo táctil.
Potencial de suposiciones incorrectas: consulte de manera responsable
Usar las funciones de medios de interacción de nivel 4 de consultas de medios y adaptar nuestros sitios en función de las características de la entrada de puntero principal o adicional disponible es una gran idea, pero tenga cuidado con las suposiciones falsas sobre lo que realmente dicen estas funciones de medios. Al igual que con métodos similares de detección de características, los desarrolladores deben ser conscientes de qué es exactamente lo que están tratando de detectar, las limitaciones de esa detección en particular y, lo más importante, considerar por qué lo están haciendo, de manera similar al problema que describí en mi artículo sobre la detección del tacto.
pointer
e hover
infórmenos sobre las capacidades de lo que el navegador determine como la entrada principal del dispositivo. any-pointer
e any-hover
informarle sobre las capacidades de todas las entradas conectadas, y combinados con información sobre la entrada del puntero principal, nos permiten hacer conjeturas fundamentadas sobre el dispositivo/escenario particular de un usuario. Podemos utilizar estas funciones para informar nuestro diseño o el tipo de interacción/funcionalidad que queremos ofrecer; pero no descarte la posibilidad de que esas suposiciones puedan ser incorrectas. Las consultas de medios en sí mismas no son necesariamente defectuosas (aunque el hecho de que la mayoría de los navegadores parecen tener todavía peculiaridades y errores aumenta los problemas potenciales). Depende simplemente de cómo se usen.
Con esto, quiero concluir ofreciendo sugerencias para “defenderse” de los peligros de las detecciones de entradas.
? No …
Suponga un único tipo de entrada. Hoy en día no se trata de “táctil o mouse/teclado”, sino de “táctil y mouse/teclado”, y los tipos de entrada disponibles pueden cambiar en cualquier momento, incluso después de la carga inicial de la página.
Sólo pasa pointer
y hover
. la entrada del puntero "principal" no es necesariamente la que utilizan sus usuarios.
Confíe hover
en en general. Independientemente de lo que sugiera hover
o any-hover
sugiera, sus usuarios pueden tener una entrada de puntero que están usando actualmente y que no es compatible con el desplazamiento, y actualmente no puede detectar esto a menos que sea la entrada principal (ya que hover: none
es cierto si esa entrada en particular carece de desplazamiento). pero any-hover: none
sólo será cierto si ninguna de las entradas es compatible con el desplazamiento). Y recuerde que las interfaces basadas en el desplazamiento generalmente no funcionan para los usuarios de teclado.
? Hacer …
Haga que sus interfaces sean "táctiles". Si detecta que hay una any-pointer:coarse
entrada (probablemente una pantalla táctil), considere proporcionar objetivos táctiles grandes y suficiente espacio entre ellos. Incluso si el usuario está utilizando otra entrada, como un mouse, en ese momento no se produce ningún daño.
Ofrezca a los usuarios una opción. Si todo lo demás falla, considere darle al usuario una opción/alternar para cambiar entre diseños táctiles o de mouse. Siéntase libre de utilizar cualquier información que pueda obtener de las consultas de los medios (como any-pointer: coarse
ser cierta) para hacer una suposición fundamentada sobre la configuración inicial de la palanca.
Recuerde sobre los usuarios de teclados. Independientemente de las entradas de puntero que el usuario pueda o no utilizar, no se olvide de la accesibilidad del teclado: no se puede detectar de manera concluyente, así que asegúrese de que sus cosas funcionen para los usuarios de teclados como algo natural.
Deja un comentario