Imágenes

Última revisión: 30 de diciembre de 2021

Optimización de imágenes

Cuando hablamos de la web, sin duda uno de los elementos principales, además del texto, son las imágenes. Y es por esto por lo que cuando hablamos de Web Performance hemos de dedicarle mucho cariño a este elemento.

El primer paso a tener en cuenta es el de la calidad y tamaño de las imágenes. En ocasiones se ve como tomamos una fotografía directamente desde nuestra cámara de fotos o dispositivo móvil y, tal y como está, se sube a Internet.

Tamaño de imagen

Tenemos cámaras de fotos que hacen fotografías a calidades de 4K, lo que significa una resolución de 3840×2160. La mayoría de las pantallas y de webs están hechas para un tamaño de Full HD, lo que significa que el tamaño que por defecto vemos (sin ampliar) es de 1920×1080. Ya de serie estamos hablando que la imagen es el doble de tamaño y que cuando la pongamos no se va a aprovechar. Así que, para empezar, deberíamos poner la imagen en un tamaño máximo que queramos. Podemos subir la imagen original, pero cuando se presente, usemos una adaptada al tamaño de la pantalla.

De la misma manera podemos hablar de las pantallas móviles. Hoy en día mediante el sistema de media-query de CSS podemos mostrar una imagen u otra dependiendo de la pantalla en la que estamos trabajando, por lo que esa imagen original que hemos subido en 4K se podría mostrar en FullHD en pantallas de escritorio, pero en HD (1280×720) en dispositivos móviles. En cualquier caso, también podemos usar los sistemas de «retina» gestionados por HTML o CSS.

En resumen, analiza el tamaño de pantalla de tu sitio y de tus usuarios y adapta el tamaño de las imágenes al necesario para cada caso. No redimensiones las imágenes por código. Una forma sencilla de hacerlo puede ser gracias a las mejoras en la etiqueta <img> del HTML5:

<img src="small.jpg" srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 1500w" sizes="50vw" alt="Imagen">

Una forma de usar este sistema de mejor forma puede ser hacer una pre carga de las distintas imágenes. De esta manera se cargarán todas las imágenes de forma asíncrona, pero sin alterar la velocidad del sitio. Para ello podríamos añadir en la cabecera del sitio algo tal que así:

<link rel="preload" as="image" href="small.jpg" imagesrcset="small.jpg 500w, medium.jpg 1000w, large.jpg 1500w" imagesizes="50vw">

También podemos ejecutar el sistema si usamos el mecanismo de <picture>. En este caso podríamos cargar las distintas imágenes con un código tal que este:

<picture>
    <source src="small.jpg" media="(max-width: 400px)">
    <source src="medium.jpg" media="(max-width: 800px)">
    <img src="huge.jpg">
</picture>

Y para acelerar la pre carga, podríamos añadir a la cabecera del sitio un código tal que este:

<link rel="preload" href="small.jpg" as="image" media="(max-width: 400px)">
<link rel="preload" href="medium.jpg" as="image" media="(min-width: 400.1px) and (max-width: 800px)">
<link rel="preload" href="large.jpg" as="image" media="(min-width: 800.1px)">

Formato de imagen

Lo siguiente que hemos de revisar es la compresión y eliminar los datos innecesarios. Con respecto a la compresión, en formatos de imagen como JPEG hay que ver si la compresión está en el 85 % (que reduce bastante sin mucha pérdida) o si en otros formatos podemos reducir la cantidad de colores de la paleta. Usar un formato apropiado en cada ocasión también es importante, ya que cada uno tiene sus puntos a favor y en contra. No es lo mismo un GIF que un PNG, un JPEG o un WebP.

<picture>
  <source type="image/webp" srcset="flower.webp">
  <source type="image/jpeg" srcset="flower.jpg">
  <img src="flower.jpg" alt="">
</picture>

Metadatos

Además, hemos de intentar reducir la cantidad de información incrustada en las imágenes como pueden ser los datos EXIF, que pueden incluir información como la de geolocalización). Si no son necesarios (podrían serlo en un medio de comunicación, por ejemplo) podrían eliminarse.

Imágenes animadas

Ahora que los GIF animados vuelven a estar de moda gracias a los memes también es importante recordar que un fichero GIF no deja de ser una serie de imágenes que se muestran una tras otra con un tiempo de frecuencia. Esto puede hacer que esta serie de imágenes se convierta en un fichero de muchos megabytes. En estos casos hay que plantearse si es mejor convertir ese GIF animado en un formato de vídeo de tipo MP4 o WebM que podría estar optimizado y ocupar mucho menos espacio.

Si queremos el mismo efecto de loop, podemos cargar el vídeo de la siguiente manera. Además, ten en cuenta que el orden en el que se cargan los vídeos importa, por lo que pondremos el <source> en el orden óptimo de carga ya que si un navegador no puede cargar un formato, pasará al siguiente, pero no al revés.

<video autoplay loop muted playsinline>
  <source src="/video.webm" type="video/webm">
  <source src="/video.mp4" type="video/mp4">
</video>

Optimización dinámica de imágenes

En ocasiones generar todos los tamaños y formatos de imágenes puede ser harto complicado, por lo que lo ideal sería generarlas en tiempo real, pero sin un coste tecnológico elevado. Y para hacer esto podemos trabajar con Thumbor.

Gracias a esta tecnología de código abierto tenemos la posibilidad de aplicar ciertos filtros como optimizar nuestras imágenes pidiéndole que las recorte, encaje, redimensione, alinee… incluso dispone de tecnología de detección facial o de elementos importantes para que al recortar use esos puntos como centro. También dispone de filtros como convertir a escala de grises o añadir una marca de agua.

Una opción rápida podría hacerse de esta manera:

<picture>
    <source src="https://thumbor.example.com/unsafe/380x0/smart/example.com/huge.jpg" media="(max-width: 400px)">
    <source src="https://thumbor.example.com/unsafe/780x0/smart/example.com/huge.jpg " media="(max-width: 800px)">
    <img src="huge.jpg">
</picture>

Codificación de los JPEG

Los archivos JPEG (Joint Photographic Experts Group), que más que un formato de archive de imagen, es un sistema de compresión, permiten varias formas de compresión.

Tras varios análisis sobre la mejor forma de comprimir, los resultados dicen que, si el archivo ocupa menos de 10 kilobytes, la mejor forma de comprimir es usando el algoritmo «baseline» o «estándar». En cambio, en aquellos archivos que ocupen más de 10 kilobytes, la mejor forma de compresión es la de «progresive».

Un detalle del sistema de compresión de los archivos JPEG es que se basa en los bloques de 8×8 de forma que se puede comprimir con base en esta regla. En la imagen, el primer recuadro está alineado en el bloque de 8×8, pero el segundo bloque no lo está.

Otro detalle importante de la calidad de los JPEG es que hay ciertos límites. Por ejemplo, comprimir una imagen al 95% o al 100% es inapreciable, pero el tamaño del fichero varía muchísimo. De la misma forma, comprimir a un 50% puede provocar una pérdida excesiva de calidad y, sin embargo, comprimir a un 51% puede llegar a ocupar menos tamaño el fichero y una menor pérdida.

Codificación de los PNG

El formato de imágenes PNG (Portable Network Graphics) se creó como sustitución del sistema GIF que tiene licencia propietaria y, además, se mejoró, ya que se conocían muchos problemas de los GIF y JPEG.

Este tipo de imágenes tiene 5 posibilidades de almacenamiento: Grayscale (escala de grises), Truecolor (color verdadero), Indexed-color (color indexado), Grayscale with alpha (escala de grises con canal alfa) y Truecolor with alpha (color verdadero con canal alfa). Además, el Indexed-color permite almacenar información como bit transparency (cada píxel puede ser totalmente transparente o totalmente opaco) o palette transparency (cada píxel puede ser semitransparente).

Uno de los mayores problemas es que la mayoría de los programas no acaba de permitir elegir entre todos estos formatos y opciones, por lo que siempre será recomendable el uso de herramientas como OptiPNG o pngcrush que convertirán la imagen a la mejor opción posible. En este caso, lo mejor será guardar la imagen en escala de grises si es el caso, o en color verdadero si es en color, ya que estas herramientas automáticamente comprueban si se puede reducir a color indexado.

Otra de las formas de reducir el tamaño de los ficheros en PNG sin perder una cantidad excesiva de calidad es utilizando la posterización (por ejemplo, a un 40%). Aunque este sistema implique una pérdida de calidad, puede reducir sobre un 25% el tamaño final del fichero.

CSS Sprites

En muchas ocasiones los sitios web tienen pequeños iconos que se van repitiendo a lo largo de las distintas páginas. Esta cantidad de iconos puede producir el efecto de un exceso de peticiones y, por ello, un número elevado de conexiones inútiles.

Como la tecnología lo permite, una buena solución es la de integrar varias imágenes en una imagen única. Esta imagen, que suele ser un PNG8, contiene una cantidad de imágenes pequeñas suficiente para no tener un tamaño excesivo y con una única imagen poder gestionar todos los elementos desde el CSS.

Este sistema, conocido como CSS Sprites permite que carguemos una única URL (que se usará en distintas zonas de la página) de forma rápida y con una única petición HTTP.

Para gestionar las imágenes, podemos hacer uso de códigos similares a los siguientes:

#nav li a {background-image:url('imagen.png')}
#nav li a.item1 {background-position:0px 0px;}
#nav li a:hover.item1 {background-position:0px -72px;}
#nav li a.item2 {background-position:0px -143px;}
#nav li a:hover.item2 {background-position:0px -215px;}

El data URL scheme

Siguiendo el mismo sistema que los CSS Sprites, podemos plantearnos que también son algo inefectivos en aquellos casos en los que estos pequeños iconos se utilicen de forma muy concreta. En esos momentos casi se puede considerar que incluir la imagen directamente en el código fuente del HTML sería más rápido.

El caso del data: URL scheme (RFC 2397) viene a resolver esta situación. La idea es incluir en el propio código el elemento en sí, codificado en Base64 que hará que no tengamos que realizar peticiones externas, sino que va incorporado en el propio código fuente, ya sea del HTML como del CSS.

El funcionamiento de este elemento sería algo tal que así:

data:[<mediatype>][;base64],<data>

El primero de los elementos <mediatype> corresponde con el MIME Type del contenido a mostrar (por ejemplo, un image/png). Al final, en codificación Base64 irá el contenido. Quedaría algo parecido a esto:

<img src=”data:image/png;base64, iVw0SUhE...bP7WlFSCC” alt="logo">

Lo interesante es que se puede utilizar dentro de los CSS, por lo que las imágenes pasarían a formar parte de un CSS de un tamaño mayor y reduciendo la cantidad de peticiones.

Lazy loading

Una de las formas que se suele aplicar a las imágenes para no sobrecargar el sistema es el llamado lazy-load. La idea de esto es que se vayan cargando los distintos elementos según se vayan necesitando o mostrando por pantalla

De esta forma al entrar en una página veríamos todas las imágenes de la primera pantalla, pero el resto de las imágenes (las que están más abajo) no se cargan. Según vamos bajando, se van cargando los elementos. Este sistema se ve también en algunos sitios que van cargando los contenidos inferiores según se va bajando por la pantalla, de forma que se hace una carga rápida de elementos, y solo se van haciendo llamadas según se van necesitando.

Desde abril de 2019 existe una forma nativa de carga en algunos navegadores de Internet que permiten el sistema de loading de forma nativa. Aunque no es compatible con todos los navegadores, la carga de imágenes suele funcionar en la mayoría de ellos, aunque no la carga de otros elementos (como los iframe).

Este parámetro permite varias opciones:

  • auto: Es el comportamiento por defecto y dependerá de la configuración del navegador.
  • lazy: El contenido se retrasa hasta que el sistema acerca el viewport (indicador de cercanía de elementos a la visualización del usuario).
  • eager: Carga los elementos de forma forzada e inmediata.

Un ejemplo de cómo se podría ejecutar es la siguiente:

<img src="imagen.png" loading="lazy" alt="imagen" width="200" height="200">
<iframe src="https://example.com" loading="lazy"></iframe>

Las imágenes en WordPress

WordPress utiliza la pantalla de Media para la subida de contenidos al sistema, además del propio editor y otros elementos repartidos por todo el panel de administración.

Tipos de imágenes

Los formatos de fichero que WordPress acepta actualmente son los siguientes:

  • .gif
  • .ico
  • .jpg / .jpeg
  • .png
  • .webp

En el caso de los JPG, PNG y WEBP, si todas las extensiones de PHP están bien instaladas, se pueden generar sus tamaños más pequeños en el mismo formato.

Teniendo en cuenta el soporte de WebP en todos los navegadores actuales, la mejor opción en cuanto a formato sería esta, WebP. Si queremos sacar el máximo provecho en su gestión, eso sí, se necesita al menos PHP 8.0 / 8.1 e ImageMagick 7.0.

Teniendo todo esto en cuenta, lo ideal sería comenzar a utilizar y subir las imágenes directamente en los formatos de WebP (y en un futuro en AVIF), para aprovechar este nuevo formato optimizado.

En caso de que tengamos ya muchos contenidos en JPEG subidos al sistema, podemos aplicar algunos plugins que sustituyen las rutas, en tiempo real, de los JPEG, generando al vuelo los contenidos en WebP. Estos plugins no funcionan correctamente o requieren una configuración adicional en algunos sistemas.

Otras opciones, quizá más recomendables, son las de crear las imágenes en formato WebP nada más subir una imagen de otro formato, y utilizar estas.

Hay que tener en cuenta que WordPress está trabajando para incluir parte de estas funcionalidades de forma nativa en el núcleo.

Tamaños de imágenes

Los tamaños por defecto de imágenes en WordPress son los siguientes.

  • Miniatura: 150px (cuadrado)
  • Medio: máximo 300px (ancho o alto)
  • Grande: máximo 1024px (ancho o alto)
  • Original: imagen original que se sube al sistema

Hay que tener presente que estos tamaños pueden ser ampliados, por ejemplo, por un tema, que añada sus propios tamaños para adaptar los destacados o cualquier otro contenido.

Si no queremos utilizar o generar determinados tamaños, lo mejor es eliminar el tamaño que no queramos. Por ejemplo, podemos dejar el tamaño en miniatura a 150×150, el tamaño medio a 0x0 (de forma que no se creará este tamaño) y el grande a 1024×1024 o a 1280×1280, que sería el tamaño más habitual de ancho de pantalla. Además, dejaremos también la imagen original.

Con estos tamaños podemos, por ejemplo, tener la imagen destacada en un blog, usando la miniatura, y en el contenido, utilizar la imagen grande, quizá enlazada a la original.

Si necesitas validar y regenerar las imágenes de los distintos tamaños puedes utilizar este plugin:

Carga retrasada de imágenes

Desde WordPress 5.5, WordPress incorpora de forma nativa un lazy-loading para las imágenes, que será ampliado y mejorado en futuras versiones.

Existen plugins que mejoran esta funcionalidad con priorizaciones de imágenes y la carga de otros elementos.