Saltar al contenido

text y su posicionamiento

x e y marcan la línea base, no la esquina. text-anchor, dominant-baseline y sus diferencias entre motores, las listas de coordenadas por carácter, y el centrado que siempre funciona.

x, y y la línea base

<text x="10" y="20">Hola</text> coloca el origen de la línea base en el punto (10, 20). La línea base es la línea imaginaria sobre la que se apoyan las letras: la parte inferior de una o la toca, y la cola de una p la atraviesa.

De ahí sale el bug inaugural: y="0" pone la línea base en el borde superior del lienzo, así que solo se ven los descendentes. Todo lo demás queda fuera.

HTML
<svg viewBox="0 0 200 60" width="400">  <line x1="0" y1="40" x2="200" y2="40" stroke="#45475a" />  <text x="10" y="40" font-size="28" fill="#cdd6f4"        font-family="system-ui, sans-serif">Apoyo</text></svg>

La línea marca exactamente dónde está la base. La p la cruza; la A se apoya en ella.

Para saber cuánto sube el texto por encima de la línea base hace falta la métrica de la fuente: el ascendente. Como regla práctica, en la mayoría de fuentes sin gracia el ascendente ronda el 0,8 del tamaño de fuente. Un texto de 28 unidades ocupa unas 22 por encima de la base, así que para que quede pegado al borde superior con un margen de 4, la y debe ser 26.

Ese cálculo aproximado se puede sustituir por uno exacto pidiendo la caja al DOM:

JS
const t = document.querySelector('text');const caja = t.getBBox();   // x, y, width, height de la geometria pintada

getBBox() sobre un text devuelve la caja del texto rasterizado, con lo que la diferencia entre caja.y y el atributo y es exactamente el ascendente usado.

text-anchor

text-anchor decide qué punto del texto se alinea con la x declarada. Tres valores:

  • start (por omisión): la x es el borde inicial del texto. En un idioma de izquierda a derecha, el borde izquierdo.
  • middle: la x es el centro.
  • end: la x es el borde final.
HTML
<svg viewBox="0 0 200 100" width="400">  <line x1="100" y1="0" x2="100" y2="100" stroke="#45475a" stroke-dasharray="2 3" />  <g font-size="16" fill="#cdd6f4" font-family="system-ui, sans-serif">    <text x="100" y="30" text-anchor="start">start</text>    <text x="100" y="55" text-anchor="middle">middle</text>    <text x="100" y="80" text-anchor="end">end</text>  </g></svg>

text-anchor se hereda, así que ponerlo en un g afecta a todos los textos de dentro. Es lo que se hace en un eje: todas las etiquetas del eje vertical con text-anchor="end" y la misma x, y quedan alineadas por la derecha sin calcular anchuras.

Nótese que start y end dependen de la dirección del texto, no del eje. En un texto de derecha a izquierda, start es el borde derecho. Eso es correcto y es la razón de que no se llamen left y right.

dominant-baseline y su historia

dominant-baseline hace en vertical lo que text-anchor en horizontal: elige qué línea base de la fuente se alinea con la y. Los valores que interesan:

Valor Alinea
auto / alphabetic La línea base alfabética. Es el valor por omisión
middle El punto medio de la altura de x
central El centro del cuadratín (em box)
hanging La base colgante, usada en escrituras índicas
text-top / text-bottom Los bordes de la caja de texto

Para centrar verticalmente un texto en una caja, los candidatos son middle y central. La diferencia: middle se calcula sobre la altura de x, que es la altura de una x minúscula y varía mucho entre fuentes; central se calcula sobre el cuadratín, que es una medida estable. En un texto en mayúsculas o en cifras, central centra mejor.

Y aquí está la advertencia práctica. dominant-baseline ha tenido implementaciones divergentes entre motores durante años, sobre todo en su interacción con alignment-baseline y con los tspan anidados. Los motores actuales han convergido bastante, pero si necesitas que un número quede centrado en un círculo con precisión de subpíxel en todos los navegadores, hay una alternativa que siempre funciona:

HTML
<text x="50" y="50" text-anchor="middle" dy="0.32em" font-size="16">42</text>

Ese dy="0.32em" desplaza la línea base hacia abajo un 32 por ciento del tamaño de fuente, que es aproximadamente la mitad de la altura de una mayúscula en la mayoría de fuentes. El texto queda centrado sobre la y declarada.

De dónde sale el 0,32: la altura de mayúscula típica ronda 0,70 em, así que su mitad es 0,35; restando la parte que ya queda por encima de la base, el ajuste práctico cae entre 0,30 y 0,35. Es un número empírico y es el que usan las bibliotecas de gráficos precisamente porque no depende de dominant-baseline.

Listas de coordenadas

x, y, dx, dy y rotate aceptan una lista de valores que se aplican carácter a carácter:

HTML
<text x="10 30 55 85 120" y="40" font-size="20">SVG!</text>

Cada carácter se coloca en su coordenada. Si hay menos valores que caracteres, los sobrantes siguen la disposición normal a partir del último posicionado. rotate es la excepción: su último valor se aplica a todos los caracteres restantes.

HTML
<!-- Todos los caracteres a 15 grados --><text x="10" y="40" rotate="15" font-size="20">Inclinado</text>

Esto sirve para efectos de texto disperso y, sobre todo, para animar cada letra por separado, que es el uso real: se generan los x desde código y se interpolan.

Un detalle: el posicionamiento por carácter opera sobre caracteres, no sobre grafemas ni sobre glifos. Un emoji compuesto de varios puntos de código o una letra con tilde descompuesta se descoordinan. Para texto latino sencillo funciona; para texto arbitrario, no.