Hace poco alguien me preguntó cómo podía hacer, mediante JavaScript, para detectar si el dispositivo que estaba usando un usuario era o no un móvil. La idea era adaptar la interfaz y parte del JavaScript a ese caso concreto, para mostrar una interfaz y funcionalidad diferente para dispositivos móviles respecto a la "versión" de escritorio de la aplicación web.
De entrada, detectar el dispositivo es una práctica muy poco recomendable. Hace ya bastantes años era lo habitual, pero en los últimos años, con la proliferación de dispositivos, navegadores, factores de forma, etc... y la velocidad con la que cambian las características soportadas por todos ellos, hacer una detección de tipo de dispositivo o navegador es una mala idea.
La cadena de agente de usuario: mala idea
Lo que se hacía hace mucho tiempo para detectar el tipo de dispositivo era utilizar la cadena de agente de usuario (User Agent) de los navegadores, para determinar el tipo de navegador, su versión y el sistema operativo en el que se ejecutaba. Esta cadena se puede obtener en el servidor fácilmente (depende de cada tecnología, pero es sencillo en todas) e incluso desde JavaScript escribiendo:
window.navigator.userAgent
Por ejemplo, esta es la cadena de usuario de un navegador Safari en un iPhone 6S Plus:
Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1
Puedes buscar algunos fragmentos de esta cadena y deducir qué navegador y sistema operativo está usando tu usuario. Por ejemplo, puedes buscar por la cadena "iPad" y deducir por tanto que se está accediendo desde un iPad. El problema es que algunos programas pueden confundirte sin querer y además cambiar la cadena de usuario es tan sencillo que cualquiera podría engañarte.
Otro ejemplo: la última versión de Internet Explorer (la 11) y Edge (el navegador que viene con Windows 10) mienten en su agente de usuario para parecer Chrome, Firefox y Safari y que sitios antiguos que usan esa técnica no utilicen "trucos" para IE que ya no tienen sentido). Esta es la cadena de agente de usuario que sacan:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393
Como ves tiene de todo, y es fácil confundirse.
Además, como decía, todos los navegadores modernos permiten falsear el agente de usuario y poner lo que queramos. Así que es más que poco recomendable usar el agente de usuario.
Total, que es muy mala idea tomar decisiones en función de la cadena de agente de usuario.
Detección de capacidades
Realmente el camino recomendable a seguir con JavaScript es siempre detectar soporte de características concretas, lo cual no depende del tipo de dispositivo, sino del navegador en sí, y además puede ir variando casi de un día para otro con las constantes actualizaciones que reciben (por algo a todos los navegadores modernos se les llama "navegadores evergreen").
Por ello lo que se hace es determinar mediante código si el navegador actual soporta o no una determinada característica que quieres utilizar antes de utilizarla.
Por ejemplo, si queremos sacarle partido a las capacidades de geo-localización del navegador actual, sea cual sea el dispositivo, podemos hacer esta simple comprobación:
if (navigator.geolocation) {
//Hacer algo con geo-localización
}
else {
//Avisar o hacer algo alternativo
}
Y actuaremos en función de si se soporta o no cada característica concreta. De hecho un navegador puede no soportarla hoy pero sí hacerlo la semana próxima en su siguiente versión.
Por otro lado si lo que necesitamos es adaptar nuestra interfaz de usuario a las restricciones propias de ciertos tipos de dispositivos, como móviles o tabletas, nuevamente es mucho más recomendable utilizar Media Queries y rejillas flexibles que tratar de determinar el tipo de dispositivo.
Por ejemplo, esta es una gráfica muy conocida (y que ya tiene algún tiempo, o sea, que ahora es todavía peor) con algunas de las dimensiones de pantalla más comunes de dispositivos con Android:
y estos son los tipos de pantalla que tienes en un ecosistema muy poco fragmentado como es el de iPhone:
Como vemos, es prácticamente imposible diseñar una interfaz para la aplicación que simplemente tenga en cuenta "que se trata de un móvil". Hace 10 años podría ser. En la actualidad, muy complicado.
En resumen
Es fácil ver que habida cuenta la enorme variedad de dimensiones de pantalla, resoluciones y densidades que existen en la actualidad, así como tipos de navegadores, versiones de éstos que cambian cada pocas semanas, y lo poco fiables que son los agentes de usuario, detectar mediante código el tipo de dispositivo es algo que no sirve para casi nada y es mucho más recomendable utilizar Responsive Web Design y detección de características concretas mediante JavaScript.