DÍA 4 / 2014

Sprites con SVG

Ni los más optimistas creyeron en su resurrección, pero 16 años después ha llegado la hora de aprovechar todas y cada una de las ventajas que nos ofrece SVG para nuestros proyectos web.


Vamos a crear un sprite con todas las imágenes que tengamos en SVG para nuestra página web.

Antes de empezar con el sprite vamos a ver el uso de las etiquetas <defs> y <use> en SVG. Estás dos etiquetas sirven para reutilizar a lo largo de un documento todo tipo de elementos que tenemos en nuestro SVG.

Todos aquellos elementos que queramos que sean reutilizados irán dentro de la etiquetas <defs></defs>. Todo lo que está incluido dentro de estas etiquetas no se va a mostrar en el navegador, para utilizarlo deberemos asignar a cada elemento que este dentro de <defs> un id="".

<defs>
  <rect id="rectangulo" width="50" height="50" x="100" y="100" fill="crimson" stroke="darkorange" stroke-width="2"/>
  <circle id="circulo" r="30" cx="200" cy="200" fill="gold" stroke="black" stroke-width="2"/>
</defs>

Ya hemos creado un rectángulo y un círculo cada uno con su correspondiente id=“”, ahora los vamos a reutilizar con la etiqueta <use>. Para reutilizar elementos a través de la etiqueta <use> necesitamos llamarlos a través del atributo xlink:href=“#ID”.

<use xlink:href="#rectangulo"/>
<use xlink:href="#circulo"/>

Ahora lo podemos usar a lo largo de nuestro SVG tantas veces como queramos, para posicionarlo utilizaremos el atributo x=“”para la coordenada horizontal y el atributo y=“” para la coordenada vertical.

<use xlink:href="#rectangulo"/>
<use xlink:href="#rectangulo" x="150" y="75"/>
<use xlink:href="#rectangulo" x="150" transform="rotate(45)"/>
<use xlink:href="#circulo"/> <use xlink:href="#circulo" x="300" y="200"/>
<use xlink:href="#circulo" transform="scale(2)"/>

A continuación os dejo un demo en CodePen para que veáis el resultado de todo lo que he estado haciendo.

See the Pen SVG - USE & DEFS by Jorge Aznar (@jorgeatgu) on CodePen.8811

Sprites

Ahora que ya hemos visto como utilizar en nuestros SVG la etiqueta <use> vamos a ver como podemos utilizar a través de ella partes que están ubicadas en otros archivos SVG.

Para el artículo he utilizado de ejemplo mi página de trabajos y cinco SVG de la propia página. Todos los SVG tienen las misma medidas, su anchura es de 595.3 pixels y su altura es de 299 pixels.

Ahora vamos a preparar el archivo que vamos a utilizar como sprite. Lo primero es crear un archivo XML con la extensión SVG, lo vamos a llamar sprite-images.svg. Las medidas que vaya a tener nuestro SVG no nos tienen que preocupar ya que vamos a ir seleccionando partes que están dentro de el, aún así y aunque no es necesario yo le he dado un viewBox="0 0 2976.5 299" vuelvo a repetir que las medidas no nos tiene que preocupar, podéis hacer todas las pruebas que queráis modificando el viewBox y si hacemos todo el proceso bien el resultado va a ser el mismo. Para aquellos que no estén familiriazados con SVG ni con el viewBox aquí os dejo un artículo que escribí sobre el viewBox, también os dejo otro de Sara Soudeian bastante más extenso y con una herramienta visual que deja bastante claro todo el funcionamiento del viewBox.

Vamos a continuar preparando nuestro archivo de sprites. Ahora vamos a ir copiando el código de los archivos que queremos incluir dentro del sprite. Vamos a copiar todo el código que este comprendido entre las etiquetas <svg></svg>, las etiquetas no las queremos. Ahora nos vamos a ir a nuestro sprite-images.svg y vamos a pegar todo el código entre dos etiquetas <g></g> a la etiqueta de apertura le vamos a asignar un id="robot-codepen" para mas tarde poder hacer referencia al id="". Si dejamos al grupo sin nombre no vamos a poder llamarlo. Con los cuatro archivos restantes vamos a hacer exactamente lo mismo, al final tendremos que tener un archivo con el siguiente código. He omitido el código que tiene cada archivo SVG para no hacer muy extenso el ejemplo.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2976.5 299">
  <g id="robot-codepen"> ----->Aquí va todo el código de robot-codepen </g>
  <g id="perfil-codepen"> ----->Aquí va todo el código de perfil-codepen </g>
  <g id="github"> ----->Aquí va todo el código de github </g>
  <g id="visible"> ----->Aquí va todo el código de visible </g>
  <g id="filtros"> ----->Aquí va todo el código de filtros </g>
</svg>

Ahora que ya tenemos preparado nuestro sprite vamos a utilizarlo. Vamos a utilizar de nuevo la etiqueta <use>, ahora en el atributo xlink:href="" le vamos a indicar la ruta donde se encuentra nuestro sprite-images.svg, en mi caso esta en la carpeta raíz así que con poner el nombre es suficiente, en caso de que estuviera en una carpeta images la ruta sería la siguiente images/sprite-images.svg. Ahora la ruta va acompañada de una almohadilla(#) y el nombre del grupo donde estaba la imagen, en primer lugar vamos a llamar al SVG robot CodePen que estaba dentro del grupo <g id="robot-codepen> quedando la etiqueta <use>de la siguiente manera:

<svg viewBox="0 0 595.3 299" class="recuadro">
  <use xlink:href="sprite-images.svg#robot-codepen"/>
</svg>

Una vez incluidas todas las imágenes el código quedará de la siguiente manera:

<svg viewBox="0 0 595.3 299" class="recuadro"> <use xlink:href="sprite-images.svg#robot-codepen"/> </svg>

-->HTML

<svg viewBox="0 0 595.3 299" class="recuadro"> <use xlink:href="sprite-images.svg#perfil-codepen"/> </svg>

-->HTML

<svg viewBox="0 0 595.3 299" class="recuadro"> <use xlink:href="sprite-images.svg#github"/> </svg>

-->HTML

<svg viewBox="0 0 595.3 299" class="recuadro"> <use xlink:href="sprite-images.svg#visible"/> </svg>

-->HTML

<svg viewBox="0 0 595.3 299" class="recuadro"> <use xlink:href="sprite-images.svg#filtros"/> </svg>

También he añadido a los SVG una clase de CSS para modificar el tamaño a nuestro gusto.

.recuadro {
    width: 350px;
    height: 176px;
}

Por desgracia si hacemos todo esto en local no vamos a ver ningún resultado a no ser que tengamos un servidor local o utilicemos en nuestro flujo de trabajo programas como CodeKit o GhostLab. Si no utilizamos ninguna de estas opciones tenemos que subir todos los archivos a nuestro propio servidor para poder ver todo en funcionamiento. A continuación he subido todo el ejemplo a mi web para que lo veáis en funcionamiento.

Un último apunte, cualquier elemento que contenga un id="" en SVG puede ser reutilizado a través de use aunque no este dentro de las etiquetas defs. Aún así desde la W3C nos recomiendan que todos estos elementos vayan dentro de defs para que nuestro código sea mas legible y accesible.

DEMO

Malas y buenas noticias

Las malas son que esto no tiene soporte en ninguna versión de Internet Explorer, tampoco en IE11. Como suele pasar este método funciona sin ningún tipo de problema en los navegadores modernos.

Las buenas es que como siempre hay alguien haciendo cosas que molan por amor al arte, en este caso Jonathan Neal se ha currado un polyfill para que funcione en Internet Explorer. Simplemente tenemos que subir el script a nuestro servidor y agregar el siguiente código con la ruta donde está alojado nuestro script a nuestro HTML:

<script src="js/svg4everybody.js"></script>

Que menos que darle una estrellita al repo de GitHub.

La demo que he subido a mi web lleva incluido el polyfill para que veáis que si que funciona en ese navegador llamado Internet Explorer.

internet-explorer-svgsprite

Comparativa

Y para terminar una pequeña comparativa.

Mi página de trabajos con los SVG cargados a través de la etiqueta <object> mas un fallback para navegadores que no soportan SVG.

sin-svg-sprite-map

Mi página de trabajos con los SVG cargados a través de images-sprites.svg sin fallback alguno.

con-svg-sprite-map

Como podéis apreciar en las imágenes me ahorro un montón de requests y la página carga bastante más rápido.

Lo único malo es que cuando utilizamos esta técnica de importar partes de otro SVG aquellos que contengan filtros no se van a importar. Tampoco importa los degradados, así que aquellos elementos que contengan degradados se quedarán de color negro.

Si quieres saber más sobre SVG puedes descargarte mi libro "SCALABLE, un libro sobre SVG" desde Leanpub.