Plantillas reutilizables (símbolos)

Las etiquetas <symbol>, <defs> y <use>


Existen situaciones donde sería conveniente reutilizar código SVG, ya sea porque hay un fragmento de código que se repite y simplemente cambio su ubicación, o porque queremos utilizar ese elemento (o combinación de elementos) en varias partes del SVG, y no queremos repetir el código varias veces.

Por ejemplo, imagina que tienes un grupo de elementos formados por un círculo con un color específico, tres cuadrados y un trayecto que los rodea. Si quisieras que ese elemento aparezca nuevamente en otra parte del SVG, en lugar de repetirlo (con el consiguiente aumento de código) podemos establecer una plantilla con <symbol> y reutilizarla con <use>.

Veamos como se hace.

La etiqueta <symbol>

El elemento <symbol> sirve justo con ese propósito. Podemos crear un elemento como si fuera una plantilla, que visualmente no se verá en nuestro documento. Luego, con la etiqueta <use> lo reutilizamos.

La etiqueta <symbol> permite utilizar los siguientes atributos:

AtributoDescripción
x / yNos permite establecer la posición del símbolo SVG en el eje horizontal, como en el vertical.
width / heightIndica el tamaño de ancho y de alto del símbolo SVG.
viewBoxDefine la región visible del símbolo.
refX / refYDefine el punto de referencia del símbolo.

Observa el siguiente ejemplo. En él, aún no utilizamos ningún <symbol>, se trata de un SVG normal y corriente, con un trayecto en su interior que dibuja la forma del logo de CSS:

<svg height="400" viewBox="0 0 21 25">
  <path d="M.1 0h21l-1.91 21.56L10.58 24 2 21.56.1 0zm17.09 4.41H4.01l.21 2.62h10.13l-.26
           2.72H7.45l.24 2.57h6.18l-.36 3.53-2.91.8-2.96-.81-.18-2.11H4.85l.29 3.85 5.46
           1.7 5.37-1.52L17.2 4.4z" />
</svg>

Vamos a hacer una modificación y en lugar de utilizar un <svg>, la cambiamos por un elemento <symbol>. La etiqueta <symbol> no pertenece a HTML, sino a SVG, por lo tanto, sólo podemos definirla en el interior de un <svg>, así que vamos a meter esta etiqueta en un lienzo más grande de SVG. Además, vamos a eliminar el tamaño de alto (y moverlo al elemento contenedor) y a añadirle un id para poder referenciarlo posteriormente:

<svg viewBox="0 0 125 80" height="400">
  <symbol id="css" viewBox="0 0 21 25">
    <path d="M.1 0h21l-1.91 21.56L10.58 24 2 21.56.1 0zm17.09 4.41H4.01l.21 2.62h10.13l-.26
            2.72H7.45l.24 2.57h6.18l-.36 3.53-2.91.8-2.96-.81-.18-2.11H4.85l.29 3.85 5.46
            1.7 5.37-1.52L17.2 4.4z" />
  </symbol>
</svg>

Comprobarás que no aparece nada visualmente. Sin embargo, el símbolo está definido. Esto ocurre porque un <symbol> es una plantilla. La hemos creado pero aún no la hemos utilizado. Para utilizarla, hay que hacer uso de la etiqueta <use>.

La etiqueta <defs>

La etiqueta <defs> es una etiqueta que se define en un elemento SVG para avisar al navegador que en su interior aparecerán definiciones de elementos u objetos que se utilizarán más tarde, para irlos procesando.

Por lo tanto, nuestro ejemplo anterior quedaría mejor de esta forma:

<svg viewBox="0 0 125 80" height="400">
  <defs>
    <symbol id="css" viewBox="0 0 21 25">
      <path d="M.1 0h21l-1.91 21.56L10.58 24 2 21.56.1 0zm17.09 4.41H4.01l.21 2.62h10.13l-.26
              2.72H7.45l.24 2.57h6.18l-.36 3.53-2.91.8-2.96-.81-.18-2.11H4.85l.29 3.85 5.46
              1.7 5.37-1.52L17.2 4.4z" />
    </symbol>
  </defs>
</svg>

Aunque no es estrictamente necesario para que funcione, se recomienda añadir los elementos <symbol> dentro de una etiqueta <defs>, de forma que el navegador pueda entender y gestionar de forma más eficaz los elementos reutilizables y dar mayor compatibilidad a navegadores antiguos.

La etiqueta <use>

Por otro lado, la etiqueta <use> la podemos usar para reutilizar símbolos o grupos que hayan sido definidos previamente. Tiene varios atributos que puedes utilizar para personalizar la plantilla que reutilizamos y cambiar su representación:

AtributosDescripción
hrefIndica un archivo y/o una referencia al elemento a reutilizar.
x / yLa posición donde será colocado el elemento (eje horizontal y vertical).
width / heightEl nuevo tamaño de ancho y alto del elemento.

El atributo importante de la etiqueta <use> es href, ya que con él indicamos el elemento que queremos reutilizar. Observa los siguientes fragmentos de ejemplo de uso de la etiqueta <use>:

<use href="#logo"></use>
<use href="file.svg#logo"></use>
<use href="https://manz.dev/logos.svg#css"></use>
  • 1️⃣ En el primer ejemplo, hacemos referencia a una etiqueta con id="logo" del documento actual.
  • 2️⃣ El segundo ejemplo, indica un fichero file.svg que debe contener el elemento con id="logo".
  • 3️⃣ Indicamos una ruta con un SVG remoto logos.svg, que debe contener un elemento con id="css".

En muchos ejemplos observarás que se utiliza el atributo xlink:href en lugar de href. Esto es una especificación antigua. Se recomienda utilizar href, ya que la primera forma está obsoleta.

Observa que en el siguiente ejemplo hemos añadido el <symbol> dentro de una etiqueta <defs> (práctica recomendada) y posteriormente, hemos definido tres etiquetas <use> que hacen referencia al id con nombre css mediante su atributo href.

Además, les damos diferentes tamaños y colores (para que hagan efecto, es necesario tener un viewBox definido en la plantilla). Visualmente, nuestro SVG con elementos reutilizables quedaría así:

<svg height="400" viewBox="0 0 125 80">
  <defs>
    <symbol id="css" viewBox="0 0 21 25">
      <path d="M.1 0h21l-1.91 21.56L10.58 24 2 21.56.1 0zm17.09 4.41H4.01l.21 2.62h10.13l-.26
           2.72H7.45l.24 2.57h6.18l-.36 3.53-2.91.8-2.96-.81-.18-2.11H4.85l.29 3.85 5.46
           1.7 5.37-1.52L17.2 4.4z" />
    </symbol>
  </defs>

  <use href="#css" x="0" width="25" fill="steelblue"></use>
  <use href="#css" x="25" width="35" fill="orangered"></use>
  <use href="#css" x="60" width="45" fill="indigo"></use>
</svg>

La etiqueta <use> se puede utilizar para reutilizar grupos definidos con la etiqueta <g>. Sin embargo, se recomienda reutilizarlos con <symbol> y <use>, que es un enfoque más apropiado.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev