CSS avanzado

Capítulo 6. Técnicas avanzadas

6.1. Imágenes embebidas

Según los estudios realizados por Yahoo! el tiempo de carga de una página media depende en un 80% de la parte del cliente y en un 20% de la parte del servidor. Los navegadores de los usuarios dedican la mayor parte del tiempo a descargar imágenes, archivos JavaScript, hojas de estilos CSS y otros recursos externos.

Por este motivo, las mejoras en la parte del cliente generan muchos más beneficios que las mejoras en la parte del servidor. De todos los elementos de la parte del cliente, las imágenes son normalmente las que más penalizan el rendimiento. Además del peso de cada imagen, el rendimiento se resiente porque cada imagen requiere realizar una petición al servidor. Como los navegadores tienen un límite de conexiones simultáneas con el servidor (entre 2 y 8), la descarga de una página con muchas imágenes se bloquea continuamente.

Como ya se explicó en las secciones anteriores, la solución para mejorar el rendimiento de las imágenes consiste en combinarlas en una imagen grande llamada sprite CSS y utilizar la propiedad background-image en cada elemento HTML.

Además de los sprites CSS existe otra técnica que permite embeber o incluir las imágenes en la propia página HTML u hoja de estilos CSS. La técnica se suele denominar "imágenes embebidas" o "imágenes en línea".

Normalmente, en las hojas de estilos y páginas HTML sólo se indica la URL de la imagen que debe descargar el navegador. En la técnica de las imágenes embebedidas no se indica la URL, sino que se incluyen directamente los bytes de la imagen, para que el navegador pueda mostrarla de forma inmediata.

Los datos de la imagen se incluyen mediante un esquema especial llamado data:, de la misma forma que las URL se indican mediante el esquema http:, las direcciones de correo electrónico mediante el esquema mailto:, etc. El esquema data: se define en el estándar RFC 2397 y su sintaxis es la siguiente:

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

El atributo <mediatype> corresponde al tipo de contenido de los bytes que se incluyen. Los tipos de contenido están estandarizados y los que utilizan habitualmente las imágenes son: image/gif, image/jpeg y image/png. Si no se indica el tipo de forma explícita, el navegador supone que es text/plain, es decir, texto normal y corriente.

El valor base64 es opcional e indica que los datos de la imagen se han codificado según el formato base64. Si no se indica este valor, el navegador supone que los bytes de la imagen no están codificados.

A continuación se muestra el ejemplo de una imagen HTML (<img>) que no se indica mediante una URL sino que se incluyen sus bytes directamente en la página:

<!-- Imagen externa que el navegador debe descargar desde el servidor -->
<img alt="Icono de un libro" width="16" height="16" src="/imagenes/icono_libro.png" />

<!-- Imagen embebida que el navegador puede mostrar directamente porque ya dispone de sus bytes -->
<img alt="Icono de un libro" width="16" height="16" src="data:image/png;base64,iV
BORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHd
hcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHjSURBVDjLdZO/alVBEMZ/5+TemxAbFUUskqAoSOJNp4KC
4AsoPoGFIHY+gA+jiJXaKIiChbETtBYLUbSMRf6Aydndmfks9kRjvHdhGVh2fvN9uzONJK7fe7Ai6algA
3FZCAmQqEF/dnihpK1v7x7dPw0woF64Izg3Xl5s1n9uIe0lQYUFCtjc+sVuEqHBKfpVAXB1vLzQXFtdYP
HkGFUCoahVo1Y/fnie+bkBV27c5R8A0pHxyhKvPn5hY2MHRQAQeyokFGJze4cuZfav3gLNYDTg7Pklzpw
4ijtIQYRwFx6BhdjtCk+erU0CCPfg+/o2o3ZI13WUlLGo58YMg+GIY4dmCWkCAAgPzAspJW5ePFPlV3VI
4uHbz5S5IQfy/yooHngxzFser30iFcNcuAVGw3A0Ilt91IkAsyCXQg5QO0szHEIrogkiguwN2acCoJhjn
ZGKYx4Ujz5WOA2YD1BMU+BBSYVUvNpxkXuIuWgbsOxTHrG3UHIFWIhsgXtQQpTizNBS5jXZQkhkcywZqQ
QlAjdRwiml7wU5xWLaL1AvZa8WIjALzIRZ7YVWDW5CiIj48Z8F2pYLl1ZR0+AuzEX0UX035mxIkLq0dhD
w5vXL97fr5O3rfwQHJhPx4uuH57f2AL8BfPrVlrs6xwsAAAAASUVORK5CYII=" />

El atributo src de la imagen del ejemplo anterior utiliza el esquema data: para incluir en la página los bytes de la imagen. El valor image/png indica que los datos corresponden a una imagen en formato PNG. El valor base64 indica que los datos incluidos están codificados según el formato base64.

Aunque el ejemplo anterior funciona correctamente, como todos los datos se incluyen en el propio código HTML, el navegador no puede hacer uso de la caché para reutilizarlos posteriormente. El resultado es que el número de peticiones HTTP se reduce drásticamente, pero aumenta significativamente el tamaño de todas las páginas HTML.

El siguiente paso consiste en utilizar las imágenes embebidas en las hojas de estilos CSS, de forma que se mantengan las ventajas del ejemplo anterior y se solucionen todas sus desventajas. Para embeber las imágenes en CSS se sigue la misma estrategia que en HTML, ya que sólo es necesario sustituir la URL por el esquema data:, tal y como muestra el siguiente ejemplo:

/* Imagen externa que el navegador debe descargar desde el servidor */
ul#menu li { background: #FFF no-repeat center center url("/imagenes/icono_libro.png"); }

/* Imagen embebida que el navegador puede mostrar directamente porque ya dispone de sus bytes */
ul#menu li {
  background: #FFF no-repeat center center url("data:image/png;base64,iVBORw0KGgo
  AAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQW
  RvYmUgSW1hZ2VSZWFkeXHJZTwAAAHjSURBVDjLdZO/alVBEMZ/5+TemxAbFUUskqAoSOJNp4KC4AsoP
  oGFIHY+gA+jiJXaKIiChbETtBYLUbSMRf6Aydndmfks9kRjvHdhGVh2fvN9uzONJK7fe7Ai6algA3FZ
  CAmQqEF/dnihpK1v7x7dPw0woF64Izg3Xl5s1n9uIe0lQYUFCtjc+sVuEqHBKfpVAXB1vLzQXFtdYPH
  kGFUCoahVo1Y/fnie+bkBV27c5R8A0pHxyhKvPn5hY2MHRQAQeyokFGJze4cuZfav3gLNYDTg7Pklzp
  w4ijtIQYRwFx6BhdjtCk+erU0CCPfg+/o2o3ZI13WUlLGo58YMg+GIY4dmCWkCAAgPzAspJW5ePFPlV
  3VI4uHbz5S5IQfy/yooHngxzFser30iFcNcuAVGw3A0Ilt91IkAsyCXQg5QO0szHEIrogkiguwN2acC
  oJhjnZGKYx4Ujz5WOA2YD1BMU+BBSYVUvNpxkXuIuWgbsOxTHrG3UHIFWIhsgXtQQpTizNBS5jXZQkh
  kcywZqQQlAjdRwiml7wU5xWLaL1AvZa8WIjALzIRZ7YVWDW5CiIj48Z8F2pYLl1ZR0+AuzEX0UX035m
  xIkLq0dhDw5vXL97fr5O3rfwQHJhPx4uuH57f2AL8BfPrVlrs6xwsAAAAASUVORK5CYII=");
}

La ventaja de utilizar las imágenes embebidas en CSS es que sólo aumenta el tamaño de las hojas de estilos y no el de todas las páginas HTML del sitio. Además, los navegadores guardan en su cache las hojas de estilos completas, por lo que el aumento en su tamaño no penaliza en exceso el rendimiento global de la descarga de páginas.

El proceso de codificación de los bytes de las imágenes según el formato base64 es una tarea más propia de programadores web que de diseñadores web. Si conoces por ejemplo el lenguaje de programación PHP puedes utilizar la siguiente instrucción:

$bytesCodificados = base64_encode(file_get_contents("/ruta/hasta/la/imagen.png"));

Si no dispones de conocimientos de programación, puedes utilizar alguna de las herramientas online que codifican directamente los contenidos del archivo indicado:

Las principales ventajas de la técnica de las imágenes embebidas son las siguientes:

  • Reduce drásticamente el número de peticiones HTTP, lo que mejora notablemente el rendimiento.
  • Permite guardar una página HTML completa en un único archivo HTML (embebiendo todas sus imágenes en su hoja de estilos o en el propio código HTML).
  • Mejora el rendimiento de las peticiones HTTPS en las que las imágenes no se guardan en la cache.

Por contra, sus desventajas son considerables:

  • El esquema data: sólo funciona en los navegadores modernos que se preocupan de los estándares (Firefox, Safari y Opera). Internet Explorer 6 y 7 no son capaces de procesar el esquema data:. Internet Explorer 8 asegura que permitirá utilizar data:, pero solamente para embeber imágenes en CSS.
  • El proceso completo es lento y poco flexible, ya que es necesario codificar las imágenes en base64 y recodificarlas cada vez que se quieren modificar.
  • Las imágenes embebidas aumentan considerablemente el tamaño de la hoja de estilos CSS. Además, la codificación base64 también aumenta mucho el tamaño de los datos de la imagen respecto a sus bytes originales.
  • Los navegadores limitan el tamaño máximo de los datos que se pueden embeber mediante data:. Algunos navegadores como Opera permiten unos 4.000 bytes de datos, mientras que el navegador Firefox permite hasta 100.000 bytes por cada data:.