Adapta tu web a pantallas Retina y otras de alta resolución



      
       Los nuevos productos de Apple tienen una gran densidad de píxeles, o lo que es lo mismo una alta resolución por espacio físico. Le dieron el nombre comercial de Retina, ya que anunciaron que sus pantallas ya tenían el número suficiente de píxeles por unidad de superficie para que el ojo humano no pudiera distinguirlos a una distancia de uso lógica. Varios especialistas han dicho que esto es exagerado, y que el ojo humano todavía tiene una capacidad mayor. No vamos a entrar en esto.

       El gran cambio que suponen estas pantallas para los diseñadores web, es que los píxeles CSS ya no son iguales a los píxeles de dispositivo. Estos dispositivos tienen una densidad de píxeles muy alta por lo que si dibujasen en pantalla las webs con el tamaño CSS natural se vería muy pequeño. Así que normalmente multiplica el tamaño de los elementos. Por ejemplo si tenemos un div de 200px de ancho, en un iPad3 lo dibujará con 400px de pantalla de ancho.

       Por tamaño las páginas se ven normales, sin embargo estamos desaprovechando esa alta resolución del dispositivo. ¿Qué podemos hacer para que nuestras webs se muestren en alta resolución en estos dispositivos?

       Si usamos técnicas nativas de la web no deberíamos tener problemas. Por ejemplo en un degradado CSS, es el navegador el que calcula el valor de color de cada píxel y el navegador que usen estos dispositivos debería estar adaptado para calcularlo con la mayor densidad de píxeles del dispositivo. Las fuentes son externas, pero suelen admitir bien cierto escalado (pueden hasta ser vectoriales) y es sencillo cambiar el tamaño de la fuente según el dispositivo.

       Así que el problema lo tenemos básicamente con las imágenes. Iconos, imágenes de fondo, galerías,... Si subimos una imagen 200x200 y el dispositivo la pone en 400x400 para que no se vea muy pequeña, pues vamos a verla con menor calidad de la que podríamos tener. Podemos usar imágenes vectoriales (svg), para iconos por ejemplo. Pero no siempre es una solución universal. No podemos vectorizar correctamente la foto de las vacaciones, por ejemplo.

       La primera solución sería poner una imagen de 400x400 con una restricción de tamaño css a 200 píxeles. Esto haría que el dispositivo “Retina” muestre la imagen con resolución 400x400 y los demás dispositivos en 200x200. El problema de esta técnica es que estamos haciendo descargar una imagen que ocupa 4 veces más a usuarios de otras plataformas que no van a notar la diferencia de calidad. Se podría hacer algo parecido con javascript, cargar una imagen de 200x200 y si el dispositivo es “Retina” cargar la de 400x400, en este caso los usuarios de estos dispositivos tendrían que descargar 2 veces la imagen, pero los demás tendrían una página óptima en uso de la red para su dispositivo.

       Al final sea cual sea la solución que usemos necesitamos saber una cosa. Si la resolución de pantalla que nos da el navegador es la real del dispositivo, o es de alta resolución y se van a redimensionar las cosas. Es decir, necesitamos saber el ratio entre píxeles dispositivo y píxeles CSS, que hasta ahora era siempre 1, pero en dispositivos “Retina” puede ser de 1.5 o incluso 2.

       Para eso existen las siguientes propiedades de distinción CSS: device-pixel-ratio y min-device-pixel-ratio.

       Una activa propiedades CSS o una hoja de estilo completa ante un ratio concreto y otra ante un ratio mínimo. Vamos a poner una hoja CSS para dispositivos “normales” y otros para dispositivos de alta resolución, por ejemplo a partir de 1.5 (la densidad del iPhone 4).

<link rel=”stylesheet” href=”css/fondosEIconos.css” />
<link rel=”stylesheet” href=”css/fondosEIconosAlta.css” media=”only screen and min-device-pixel-ratio:1.5” />

       Esto sería según el tipo estándar, pero por ahora esta distinción lleva prefijo de navegador. Así que una declaración CSS completa sería:

@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
only screen and (min--moz-device-pixel-ratio: 1.5),
only screen and (-o-min-device-pixel-ratio: 3/2),
only screen and (-ms-min-device-pixel-ratio: 1.5),
only screen and (min-device-pixel-ratio: 1.5) {

}

       Aunque la lógica dice que la declaración de Firefox debería ser -moz-min-device-pixel-ratio, por ahora funciona con min--moz-device-ratio. Hay que tener cuidado con la declaración de opera, ya que funciona con fracciones, no con números con decimales, y por último la declaración de IE me la he inventado, supongo que con IE10 y Windows 8 más orientado a dispositivos móviles lo soportará.

       ¿Por qué poner toda esta parafernalia si la mayoría de pantallas de alta resolución son de Apple? En los nuevos Mac Book Pro se puede navegar usando cualquiera de los navegadores de nueva generación, salvo IE. Además podemos prever que los demás fabricantes de dispositivos irán en este camino y en un futuro no muy lejano una buena parte de la pantallas que se vendan tengan una densidad de píxeles alta.

       También podemos detectar la densidad de píxeles en javascript y actuar en consecuencia:

var pr = 1;
if(window.devicePixelRatio !== undefined)
    pr = window.devicePixelRatio;

if (pr>=1.5){
    //hacer algo
}

       Primero detectamos si la propiedad existe, para no tener errores en navegadores antiguos. Si es antiguo seguramente estemos en un dispositivo con un ratio de píxel de 1, y si no es así tampoco podemos averiguarlo, así que nos da igual. ¿Y qué es hacer algo? Podríamos cargar las imágenes o ficheros CSS de forma condicional desde javascript según la densidad de píxeles. También se podrían redimensionar elementos, e incluso ofrecer un botón para ver una imagen en alta resolución. Si tenemos una galería de imágenes y las ofrecemos por defecto en alta resolución en dispositivos “Retina” se verán muy bien, pero ¿cuánto tardará en cargar la página? Así que lo mismo es buena solución mostrar imágenes normales y dar la posibilidad de “ver en HD”.

       Otra duda que nos puede surgir es ¿cuántas versiones de la misma imagen tengo que tener? ¿Una para ratio 1, otra para ratio 1.5, otra para ratio 2? Y si hay un ratio 1.75, ¿qué imagen uso? ¿La de 1.5, la de 2, hago una de 1.75? Se me ocurre que se podrían pedir las imágenes mediante llamadas ajax, y devolverlas inline (es decir el código interno de la imagen como chorizo de datos). Pero en esa petición se podría decir al servidor el píxel ratio y el servidor podría redimensionar la imagen a medida. (Por ejemplo coger la imagen para ratio 2 y redimensionar a 1.75). Así tendríamos la resolución óptima del dispositivo sin hacer una trasferencia mayor de la necesaria. Aunque gastaríamos tiempo de CPU de servidor en cada carga de página.

       Es un tema complicado, todavía muy en sus inicios, y esperemos que nos den mejores herramientas para no volvernos locos. Pero algo ya podemos ir haciendo con CSS condicional y un poco de javascript.