Textos en trayectos

La etiqueta <textPath>


En algunas ocasiones, es posible que nos interese definir un texto, pero no tenerlo en una disposición normal, sino que queremos que siga una forma específica o un trayecto personalizado. Para ello, tenemos a nuestra disposición la etiqueta <textPath>, que permite indicar un texto en un trayecto personalizado.

El elemento <textPath>

La etiqueta <textPath> se indica en el interior de una etiqueta <text> para modificar el texto y colocarlo en un trayecto personalizado mediante una forma específica o un trayecto <path>, que generalmente se colocará en el apartado de definiciones <defs>.

Con ello, podemos decirle a nuestro SVG, que el texto contenido en el elemento <textPath> debe seguir una forma concreta, generalmente indicada en el atributo href, mediante un id.

Estos son los atributos disponibles en el elemento <textPath>:

Atributo Valor por defecto Descripción
href none Referencia a un trayecto previamente definido.
textLength 0 Distancia entre carácteres. Más información.
lengthAdjust spacing Ajuste de carácteres. Más información.
spacing exact Indica como gestionar el espacio entre glifos. Valores: auto o exact.
startOffset 0 Espacio en el que comienza el desplazamiento.
🧪 method align Renderiza el texto estirando o alineando. Valores: stretch o align.
🧪 path none Usa el valor del atributo d de un de SVG, en lugar de una figura indicada en href.
🧪 side left Define en que lado va a definir el texto. Valores: left o right.

Veamos un ejemplo para entenderlo mejor.

Referencia a un trayecto

Antes de empezar, comencemos con un fragmento simple, donde solo tenemos un bloque de texto normal. Vamos a extraer algunos de sus atributos y externalizarlo en CSS, para enfocarnos en los puntos clave.

<svg viewBox="0 0 250 100" height="300">
  <text x="10" y="50" font-family="Jost" font-weight="800" font-size="8">
    ¿Experiencia única? Código Konami en Manz.dev
  </text>
</svg>

Ahora, vamos a crear un arco utilizando un <path>. Observa en la siguiente demo como se muestra el arco. A continuación vamos a meter este <path> en un bloque de definiciones <defs> para que no se muestre y utilizarlo posteriormente:

<svg viewBox="0 0 250 100" height="300">
  <path id="arc" d="M10,75 A20 10 0 0 1 240,75" stroke="black" fill="none">
</svg>

Una vez hecho esto, en el interior del elemento <text> indicamos un <textPath> al que hacemos referencia al id de nuestro arco. Con esto le estaremos diciendo que utilice el trayecto <path> como base para el texto, por lo que este se adaptará a su forma. Además, mediante los atributos textLength y dx que vimos en artículos anterior, ajustamos donde aparece el texto:

<svg viewBox="0 0 250 100" height="300">
  <defs>
    <path id="arc" d="M10,75 A20 10 0 0 1 240,75">
  </defs>

  <text x="10" y="50" dx="3" textLength="250">
    <textPath href="#arc">
      ¿Experiencia única? Código Konami en Manz.dev
    </textPath>
  </text>
</svg>

<p>Valor de <code>textLength</code>:
  <input class="tl" type="range" min="0" max="500" value="250">
  <output>250</output>
</p>
<p>Valor de <code>dx</code>:
  <input class="dx" type="range" min="0" max="50" value="3">
  <output>3</output>
</p>
const text = document.querySelector("text");
const tl = document.querySelector("input.tl");
const dx = document.querySelector("input.dx");

tl.addEventListener("input", () => {
  tl.nextElementSibling.value = tl.value;
  text.setAttribute("textLength", tl.value);
});
dx.addEventListener("input", () => {
  dx.nextElementSibling.value = dx.value;
  text.setAttribute("dx", dx.value);
});
text {
  font-family: "Jost";
  font-weight: 800;
  font-size: 8px;
  fill: indigo;
}

Observa que los atributos dx y textLength están ubicados en el elemento <text>.

Desplazamiento y espaciado

Mediante el atributo startOffset puedes definir en que momento del trayecto comienza a mostrarse el texto, ajustando su desplazamiento inicial. Funciona de una forma muy similar al atributo dx visto hasta ahora.

<svg viewBox="0 0 250 100" height="300">
  <defs>
    <path id="arc" d="M10,75 A20 10 0 0 1 240,75">
  </defs>

  <text x="10" y="50" textLength="250">
    <textPath href="#arc" spacing="auto" startOffset="20">
      ¿Experiencia única? Código Konami en Manz.dev
    </textPath>
  </text>
</svg>
text {
  font-family: "Jost";
  font-weight: 800;
  font-size: 8px;
  fill: indigo;
}

Por otro lado, el atributo spacing permite indicar entre los valores auto y exact (este último por defecto), donde indicas si el trayecto debería ser renderizado según un algoritmo del navegador o exactamente como está definido en los atributos del trayecto de base.

Cuidado con los atributos path, method y side, puesto que en la actualidad no tienen buen soporte en navegadores.

¿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