> Manuales > Taller de CSS

Sprites e imágenes embebidas usadas con CSS para la optimización de documentos HTML.

En el presente artículo trataremos:

¿Qué es un sprite?

Numerosas son las acepciones del término, inicialmente empleado para referirse a bitmaps independientes del cuerpo del escenario, que podrían ser animados sobre él de forma separada –nos referimos a la edición en inglés por ser mucho más amplia y precisa, a nuestro entender-. Para una discusión completa acúdase allí:
http://en.wikipedia.org/wiki/Sprite_(computer_graphics)
En nuestro caso –en lo que se refiere a HTML y CSS- es un conjunto de imágenes agrupadas en una única imagen, a cada una de ellas se accede mediante un desplazamiento respecto del borde superior izquierdo, cota (0,0), y sus dimensiones absolutas. Es, por tanto un método de agrupación de imágenes que, posteriormente, pueden ser tratadas de forma independiente.


Sprite utilizado para diversas aplicaciones y logos de Google


Ilustración de un sprite de una animación con CSS –por ejemplo-

Por qué se optimiza el código HTML

Uno de los problemas de retardo más importantes en la carga de documentos desde Internet es el tráfico HTTP y las propias capacidades de los navegadores para gestionarlo. El punto crítico más importante suele ser el fraccionamiento de llamadas, consecuentemente, el número de archivos es determinante.

Si se utilizan múltiples imágenes, se realizarán otras tantas llamadas al servidor y una sobrecarga directamente proporcional al acceso a la página, por el contrario, se reducirá sustancialmente esto con el uso de sprites, dado que cada uno de ellos –o uno único- descargará múltiples imágenes con una sola llamada –un único archivo-. Bien es cierto que el peso cuenta, pero en menor cantidad de lo que pesa el tráfico de llamadas en sí, dentro de los límites de la moderación y hablando proporcionalmente.

Fijémonos, por poner un caso, en las figuras que siguen, las tres primeras figuras de una supuesta barra de herramientas, se han agrupado en una única en formato sprite, que utilizaremos en nuestros ejemplos; ahora en la carga de la página ahorraremos dos accesos al servidor al tener que referenciar una única imagen.

Generación de sprites

Usualmente dispondremos de las imágenes por separado y desearemos generar el sprite correspondiente.

Deberemos acudir a utilidades que automaticen la tarea y las hay, afortunadamente, abundantes y de calidad que, además de generar el sprite, nos dan información de cómo insertar las imágenes, sus cotas, dimensiones y código para utilizarlas en nuestra CSS.

Algunos de los lugares de Internet que nos proporcionan esas facilidades son:

En las figuras anteriores mostramos las vistas de dos de los lugares, el segundo de ellos –instantsprite.com-, que funciona con Firefox, Chrome y Opera , trabaja de la siguiente forma:

Caso de usarse Internet Explorer recomendamos CSS Sprites Generator, de funcionalidad muy similar, algo menos versátil. Crea adicionalmente, eso sí, imágenes con fondo transparente en formato png.

Ejemplo de uso de sprites con CSS

En la figura adjunta se muestra una colección de seis figuras –un sprite- que muestra el estado de tres botones en forma normal y cuando se pasa el botón por encima de ellos –efecto hover-. No son más que las tres figuras inicialmente mostradas más otras tres que hemos construido pasándolas a vídeo inverso, su efecto es suficientemente ilustrativo para nuestro ejemplo. Las hemos expuesto en doble fila, como una opción adicional más y así poder ilustrar también cómo manejar ese tipo de sprites multilínea.

El ejemplo base lo hemos tomado de un editor de textos HTML 5, de tipo Rich-Text Editing, una simple área de edición con el atributo contenteditable, del que hemos hablado ya en nuestros anteriores artículos:

Las modificaciones introducidas se refieren a la sustitución de los viejos botones de comando allí existentes, por un diseño mediante CSS de la forma: Listado 1:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sprite-1</title>

<style>
#opciones {
position: relative;
}
#opciones li {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
top: 0;
}
#opciones li, #opciones a {
height: 24px;
display: block;
}

#negrilla {
left: 0px;
width: 31px;
background: url('sprite-1.png') 0 0;
}
#negrilla a:hover {
background: url('sprite-1.png') 0 -24px;
}

#italica {
left: 31px;
width: 30px;
background: url('sprite-1.png') -31px 0;
}
#italica a:hover {
background: url('sprite-1.png') -31px -24px;
}

#subrayado {
left: 61px;
width: 30px;
background: url('sprite-1.png') -61px 0;
}
#subrayado a:hover {
background: url('sprite-1.png') -61px -24px;
}

#textBox {
position: absolute;
top: 40px;
width: 600px;
height: 300px;
border: 2px #000000 solid;
padding: 10px;
overflow: scroll;
background-color: yellow;
}
</style>
</head>

<body>

<ul id="opciones">
<li id="negrilla"><a href="#" onclick="document.execCommand('bold',false,'');"></a></li>
<li id="italica"><a href="#" onclick="document.execCommand('italic',false,'');"></a></li>
<li id="subrayado"><a href="#" onclick="document.execCommand('underline',false,'');"></a></li>
</ul>

<section id="textBox" contenteditable="true">
<h1 style="color: red">Título</h1>
<p>Escribir aquí...</p>
</section>
</body>
</html>

El listado que sigue es una simplificación del anterior, en el que hemos agrupado algunos estilos, con la finalidad de hacer más eficiente el HTML resultante y, por ende, la carga y el redibujado más eficiente. Lo ponemos aquí y lo hemos hecho así como mera ilustración de una mejora en el diseño y prestaciones a costa, si acaso de una menor legibilidad. Todo será a criterio del programador. Insistimos en que ambos son estructuralmente idénticos.

Listado 2:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sprite-1</title>

<style>
#opciones {
position: relative;
}
#opciones li {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
top: 0;
}
#opciones li, #opciones a {
height: 24px;
display: block;
}

#negrilla, #italica, #subrayado, #negrilla a:hover, #italica a:hover, #subrayado a:hover {
background: url('sprite-1.png');
}

#negrilla {
left: 0px;
width: 31px;
background-position: 0 0;
}
#negrilla a:hover {
background-position: 0 -24px;
}

#italica {
left: 31px;
width: 30px;
background-position: -31px 0;
}
#italica a:hover {
background-position: -31px -24px;
}

#subrayado {
left: 61px;
width: 30px;
background-position: -61px 0;
}
#subrayado a:hover {
background-position: -61px -24px;
}

#textBox {
position: absolute;
top: 40px;
width: 600px;
height: 300px;
border: 2px #000000 solid;
padding: 10px;
overflow: scroll;
background-color: yellow;
}
</style>
</head>

<body>

<ul id="opciones">
<li id="negrilla"><a href="#" onclick="document.execCommand('bold',false,'');"></a></li>
<li id="italica"><a href="#" onclick="document.execCommand('italic',false,'');"></a></li>
<li id="subrayado"><a href="#" onclick="document.execCommand('underline',false,'');"></a></li>
</ul>

<section id="textBox" contenteditable="true">
<h1 style="color: red">Título</h1>
<p>Escribir aquí...</p>
</section>
</body>
</html>

Trabajo con imágenes embebidas

Queremos decir con ello el insertar directamente los bytes de la imagen en el archivo que contiene el documento HTML –o en su caso en el archivo CSS-. La gran ventaja obtenida es nuevamente el ahorro de tránsito en la red, dado que no habrá que obtener la o las imágenes de archivos externos. Es un paso más allá en la línea que hemos iniciado con el uso de los sprites. Para obtener el código de las imágenes en el formato estándar para ser embebidas –normalmente se usará el Base64-, acudiremos a utilidades disponibles en Internet, como por ejemplo las Web Coder Tools:
http://webcodertools.com/imagetobase64converter

El modo de trabajo es del todo simple:

Para referirnos a una imagen de fondo en un estilo para nuestro ejemplo concreto, la sintaxis a emplear es:
background: url(data:image/png;base64, …)

Ninguna de las opciones que se nos dan por defecto.

El ejemplo que sigue es exactamente el mismo que el anterior, pero prescindiendo de la imagen externa e incluyéndola como imagen embebida en el documento HTML. Obsérvese, sobre todo, lo indicado de cómo referenciar la imagen embebida y cómo el resto del código permanecerá invariante.

Naturalmente, todo el sistema de acotaciones de los sprites ha de ser realizado previamente sobre la imagen real y el modo de trabajar con imágenes embebidas será habitualmente un último paso del proceso de nuestros desarrollos estándar con las imágenes reales. Es visto de alguna manera, una etapa final de optimización de código.

Listado 3:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sprite-1</title>

<style>
#opciones {
position: relative;
}
#opciones li {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
top: 0;
}
#opciones li, #opciones a {
height: 24px;
display: block;
}

#negrilla, #italica, #subrayado, #negrilla a:hover, #italica a:hover, #subrayado a:hover {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFsAAAAwCAMAAABJ2/YyAAADAFBMVEX9/f33+fj09fTv8fDv7/Hu8O/r7Ovn6ejm5ujm6Ofj4+Tf4OHe3+Ha2tzX19nU1NXMzMzDw8PBwb+8vLy2uLezs7Oqq6qkpKSenqCbm5yUlJSRkI6Li4uGhoiJiYeGiIeCgoJ/gYCBf4B/f4GAgH5+gH+Af359fX15d3h2d3l0dHRucG9rbGtoaGZjY2NcXFxXWVhVVVVMTExDQ0I8PDwzMzMqKiopJygoKCYlJSMhIR8gHx0dHBsZFxgZGBYYFx YUExMRDxAPDhESEQ8QDg8LCgsHCQgJBwgGBggIBgcCAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAn8j/UAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFjklEQVRYhZVXgW7iOBBNxCJvZSlGcIElp+ZkQJU3CisI4GKscso2qtL//6GbsRPb lDarmyTO+L2ZNxMrIiaKBedw2kEIvkJHGHBlCWcmgtt4m2LHlWO5z4DASERfWhwNsUDnA2wErLAioWBgQ9p/YouID/L/DLL8QycfWVP7y5D/2ffNAvCB2oh/ tqKx0xh+Zj7cWXyvHQfevXbYp/B8nFeHfbYt53EQdlOZzkWRp71AHPQdL4+HjEUTvs3Cvrkv9etYsnS/XfiHvtWOSVFOKe25OGS3x4SSaFokjkZt/zg7uaO0qjLixYNsQNiuYCT2wFPnALQ9MXRLL9313T3kTu1ZejzMqYk2tgq042hRLWmnBVds34PYDLsTRahwvNV2tlcSzoxB7R7yLAFsd5zSODARxyYUKclQswz 4QDsC7WqaK7UEn9xpg7FTxcK5Z0m0Vwyqs+3n2gS09yw+KPVA7rORz3RODTX6wBJ8ZhbReNppmwB4B0fjeAwXId/2uqJkr3RCSEw AicmIj0fWcFapGaaORu PxGIDRaDM2OKrnmoOzzUwAJMMEfgcJGROCUqQCbXrSB3gXEMGRE28TZIyNx/Ym7BTiYlrow+4kKHXh2Dd5AAcuulZa7U6ynFmejgk NtfNKH4VPRTMshYOkaZo VYrlYpJ41fROoRin9TinD8wEmDwjBnVPyYA0jGPbdzWH6wCmOWK811sAFOtYojzbUKBN7S/AemPDz77cMzn8GGLYFFgTAe9IzNPFw0vm JoF8ZRoh7KFB5ijjUYgZi NDElEoY8A33GHlmYyhKfCVksZyyB9AQnyU1TlE6oiH6iLMoYXVsHp4kJA7YzzMZIZzATjNo2 bBbUSUyAqQjajxMUskWtblccyySrxHdNXaClE8qZVeweyi8JjhMefXtc9998GGE7sFojsDZHYLChWK8ezX7BXmsA+i3D2qJr0WXb+Kj BXYYQwu1KBO98sbGENXCfDN rtX/qwfjSx3GeAG4l2yIbYZpBtW9hDdO/855YPZvNBNv9D38UgKwa6Atb0/XXIcGd3bKjTwO/J21Dtz/punIYYrCz+sN732k3g3WuHSjxaO7hIZ/Nyme1D/ilM1Hu eF1XjBRzbbKezUrYnsSzDvoPai2kmq/ly9+br36xoU+fZUdZBZ95dTpWu22Mua1cZ19trs4VS6V9l7Vc0yAZELsJcv94AZROJXq Y9HfbdLOhcVtPpXrdN8yEb6abdpVsFnutGOOm3xURBQJMj/+60m/YNl7BpmjllczopsbUOaTeNMwhbTI+6fXvHyijUCuOZY8EkYp nC0YagdvNuc9s5TY8lpVtwa0QAF00gLiepDObN+8pzcyqhhFzqLhHMaFuroe+5bGaUXuuO/t2I34FWSQsVatvKb8YF7fbf38cfz55dR U8gao66hr41DPS5rt9ri4m6rwyzlB50NzHxzaq2PowFxQValrqjIRu+l7U1QFKaKj2hM9C+duhT7e1EZ7K+Me5S4fWk s8WEax2w0dMVp9fXV41f/B8T9vdBX68Gql9exIsLLVI63ahA+VqvIO5Vv+r6WlXVNufb3a4y1IvVhtpXqAZv/lUpeYHzCgAcUFNrAXdr9UWr8xmCnemr0GA19 hb1f4NirV+MQW600eoCIvX1glqq1r1dNFTgfl53YE+Ddn5FDzJBQ0JnZymVi1DwnkA/6nLG66LQVQjgAMeZX1Rv kG8YP9dcA3TpMwzmaQ3fNKglEYfK8oyoPONN4iF/Sh997hhryBZSQq9IqJ5x8SfFoxzKIisRNYF4yk4mhyRrWPi MoQ5Q6lH2etidfEYRpMziKOy700XBrrB87hsXrg8DSf8YEhDMPZ+7NMvJ7hGhcRHV7uPfbQA2m40 Dboy7XUO/SeBmo+H2DwYw2Zb+D7GrXPoWJtj2AAAAAElFTkSuQmCC);
}

#negrilla {
left: 0px;
width: 31px;
background-position: 0 0;
}
#negrilla a:hover {
background-position: 0 -24px;
}

#italica {
left: 31px;
width: 30px;
background-position: -31px 0;
}
#italica a:hover {
background-position: -31px -24px;
}

#subrayado {
left: 61px;
width: 30px;
background-position: -61px 0;
}
#subrayado a:hover {
background-position: -61px -24px;
}

#textBox {
position: absolute;
top: 40px;
width: 600px;
height: 300px;
border: 2px #000000 solid;
padding: 10px;
overflow: scroll;
background-color: yellow;
}
</style>
</head>

<body>

<ul id="opciones">
<li id="negrilla"><a href="#" onclick="document.execCommand('bold',false,'');"></a></li>
<li id="italica"><a href="#" onclick="document.execCommand('italic',false,'');"></a></li>
<li id="subrayado"><a href="#" onclick="document.execCommand('underline',false,'');"></a></li>
</ul>

<section id="textBox" contenteditable="true">
<h1 style="color: red">Título</h1>
<p>Escribir aquí...</p>
</section>
</body>
</html>

Jaime Peña Tresancos

Escritor. Colaborador habitual de revistas de tecnología y experto en nuevas tec...

Manual