Una línea de texto de tamaños mixtos puede superar los valores de line-height de ambos tramos porque la alineación por la línea de base combina sus extensiones superiores e inferiores. Esta guía muestra cómo diagnosticar esa altura adicional y ajustar una fila con dos etiquetas en un navegador de escritorio para Mac.
¿Por qué el tramo más alto no determina la altura de línea?
Considera un encabezado de página abstracto que contiene una Label A grande junto a una Label B pequeña. Ambos tramos tienen line-height: 40px, pero la fila que los contiene mide más de 40 píxeles CSS. Esto se debe a cómo el diseño en línea alinea los cuadros antes de calcular la línea que los engloba.
Para el texto en línea normal, el navegador calcula la contribución de altura de cada cuadro, los alinea verticalmente y luego engloba sus extensiones combinadas. Con la alineación por la línea de base, el extremo superior más alto y el extremo inferior más bajo pueden pertenecer a tramos distintos. Por eso, el resultado puede superar la contribución individual de cualquiera de ellos. El elemento padre también aporta un cuadro invisible de tamaño mínimo, llamado tradicionalmente strut. W3C: Cálculos de altura de línea
La línea de base es la referencia de alineación del texto. No es el punto medio vertical de su contribución al interlineado. Dar a textos de distintos tamaños el mismo interlineado no les proporciona la misma distancia por encima y por debajo de esa línea de base. El valor inicial de vertical-align es baseline. MDN: vertical-align
Mantén separadas tres mediciones: las métricas de ascenso y descenso de la fuente, los límites visibles de las letras concretas y el espacio que contribuye al diseño de la línea. El fondo de color o el rectángulo de selección de un tramo no deben considerarse una medición directa del cuadro de línea que lo engloba; CSS distingue la geometría de dibujo en línea de los cálculos del interlineado. W3C: Interlineado y medio interlineado
¿Cómo pueden dos contribuciones de 40px producir una línea de 48,4px?
Para texto normal alineado por la línea de base con un interlineado explícito, el cálculo útil consiste en restar del interlineado el ascenso más el descenso de la fuente y distribuir por igual el espacio restante arriba y abajo. Ese espacio adicional se llama interlineado; cada mitad se denomina medio interlineado. El borrador de trabajo CSS Inline Layout Level 3 del W3C describe este cálculo y admite valores negativos de interlineado. Su estado de borrador no garantiza la compatibilidad de los navegadores con todas las propiedades más recientes que contiene. W3C: Cálculo de los límites del diseño
Los siguientes datos son ilustrativos; no son mediciones de Arial ni de ninguna fuente para Mac. Supongamos que la contribución del strut del elemento padre coincide con la del tramo pequeño y que no hay otro contenido en línea ni desplazamientos verticales.
| Contribución | Ascenso de la fuente | Descenso de la fuente | Interlineado | Medio interlineado | Por encima de la línea de base | Por debajo de la línea de base |
|---|---|---|---|---|---|---|
| Tramo grande | 32px | 8px | 40px | 0px | 32px | 8px |
| Tramo pequeño | 9.6px | 2.4px | 40px | 14px | 23.6px | 16.4px |
| Strut del elemento padre | 9.6px | 2.4px | 40px | 14px | 23.6px | 16.4px |
En este ejemplo de alineación por la línea de base, toma por separado la mayor extensión a cada lado: max(32, 23.6, 23.6) + max(8, 16.4, 16.4) = 48.4px. Cada contribución suma 40px, pero el tramo grande determina el extremo superior, mientras que el tramo pequeño y el elemento padre determinan el inferior. Este resultado calculado se deriva del cálculo de diseño documentado; no es una medición prevista del navegador. W3C: Modelo de diseño en línea
La pregunta de diagnóstico es, por tanto: ¿qué elemento determina cada extremo? Reducir el interlineado del tramo pequeño puede eliminar su contribución inferior y dejar intacta una contribución idéntica del strut del elemento padre.
¿Cómo puedes reproducirlo e inspeccionarlo en un Mac?
Usa Chrome en tu Mac para seguir estos pasos. Abre una pestaña nueva, ve a about:blank y pulsa Command + Option + J para abrir la Consola. Chrome documenta este atajo para ejecutar JavaScript. Chrome DevTools: Descripción general
Ejecuta el programa completo de abajo en esa pestaña en blanco. Crea tres filas sintéticas con las mismas etiquetas, muestra sus mediciones y usa una raíz de sombra para agrupar los estilos de la demostración. No se requieren instalaciones de paquetes ni bibliotecas externas. Si lo ejecutas de nuevo, reemplaza la demostración anterior.
(async () => {
document.getElementById('line-box-demo')?.remove();
const host = document.createElement('div');
host.id = 'line-box-demo';
document.body.append(host);
const root = host.attachShadow({ mode: 'open' });
const style = document.createElement('style');
style.textContent = `
:host { display: block; padding: 24px; color: #222; background: #fff; }
.label { margin: 20px 0 6px; font: 14px Arial, sans-serif; }
.row { font: 12px/40px Arial, sans-serif; white-space: nowrap;
margin: 0; padding: 0; border: 0; background: #e8eef4; }
.large { font-size: 40px; line-height: 40px; }
.small { font-size: 12px; line-height: 40px; }
.trim-span .small, .trim-both .small { line-height: 12px; }
.trim-both { font-size: 40px; }
`;
root.append(style);
const cases = [
['', 'Shared 40px line-height'],
['trim-span', 'Smaller span only'],
['trim-both', 'Parent and smaller span']
];
const rows = cases.map(([className, label]) => {
const caption = document.createElement('p');
caption.className = 'label';
caption.textContent = label;
const row = document.createElement('div');
row.className = `row ${className}`;
for (const [size, text] of [['large', 'Label A'], ['small', ' Label B']]) {
const span = document.createElement('span');
span.className = size;
span.textContent = text;
row.append(span);
}
root.append(caption, row);
return { label, row };
});
await document.fonts.ready;
console.table(rows.map(({ label, row }) => ({
case: label,
parentLineHeight: getComputedStyle(row).lineHeight,
largeLineHeight: getComputedStyle(row.children[0]).lineHeight,
smallLineHeight: getComputedStyle(row.children[1]).lineHeight,
rowHeight: row.getBoundingClientRect().height
})));
})();
El programa espera a document.fonts.ready, que se resuelve cuando termina la carga de fuentes del documento y el trabajo de diseño relacionado. Si luego introduces otra fuente o cambias el contenido, vuelve a medir una vez que se hayan aplicado los cambios. MDN: FontFaceSet.ready
Interpreta las tres filas como una comparación controlada. En la primera, ambos tramos y el elemento padre tienen un interlineado de 40px. En la segunda, solo se reduce a 12px el interlineado del tramo pequeño. En la tercera, también se cambia a 40px el tamaño de fuente del elemento padre, de modo que su strut coincide con el tamaño de fuente y el interlineado del texto grande. Si la segunda fila sigue siendo alta, pero la tercera se reduce, esa comparación identifica la contribución del elemento padre.
Usa los resultados de tu navegador en lugar de esperar el valor ilustrativo de 48,4px. El programa mide cada fila con getBoundingClientRect(), que devuelve el rectángulo delimitador de un elemento, incluidos el relleno y los bordes. En este caso, las filas no tienen ninguno de los dos, contienen una sola línea sin ajuste de texto y tienen altura automática, por lo que sus alturas sirven como aproximaciones útiles a las alturas de los cuadros de línea. Medir un tramo con la misma API daría el rectángulo de ese tramo, sin exponer directamente el cuadro de línea que lo engloba. MDN: getBoundingClientRect()
¿Qué debes comprobar en un diseño existente?
Haz clic en el texto pertinente mientras mantienes pulsada la tecla Control y elige Inspeccionar. En Elements, inspecciona ambos tramos y el bloque contenedor. Usa Styles para rastrear las declaraciones y Computed para ver los valores aplicados; activa Show All cuando necesites inspeccionar propiedades heredadas. Chrome documenta estas vistas y sus filtros de propiedades. Chrome DevTools: Referencia de funciones de CSS
Registra font-family, font-size, line-height, display y vertical-align para cada elemento participante. Empieza por el elemento padre, en lugar de fijarte solo en los dos tramos. Luego sigue estos pasos para aislar la causa:
- Confirma el modelo de diseño. Determina si los elementos hijos participan en el flujo en línea normal o son elementos flex o grid.
- Confirma que haya una sola línea. Usa un área de prueba amplia y etiquetas sintéticas breves para que el ajuste de línea no confunda la medición.
- Comprueba la alineación. Elimina temporalmente los desplazamientos de la línea de base y la alineación vertical no predeterminada antes de aplicar el cálculo sencillo anterior.
- Cambia un solo elemento contribuyente. Reduce el interlineado del tramo pequeño, mide y luego prueba por separado la contribución de la fuente y del interlineado del elemento padre.
- Restaura las condiciones reales. Una vez identificada la causa, vuelve a comprobar la fuente prevista, el ancho disponible y el texto.
Comprueba también la herencia. Un line-height: 1.2 sin unidades transmite un multiplicador que cada elemento descendiente aplica a su propio tamaño de fuente. Un valor de longitud como 40px transmite una longitud fija, salvo que se sobrescriba; los porcentajes se calculan respecto al tamaño de fuente del elemento que los declara. Estas opciones pueden dar un interlineado inesperadamente amplio al texto pequeño. normal depende de la fuente y del navegador, por lo que no sirve como valor numérico fijo. MDN: Valores y herencia de line-height
¿Qué ajuste se adapta al resultado previsto?
Elige el ajuste según lo que representen las dos etiquetas. Un encabezado compacto formado por etiquetas separadas tiene requisitos distintos de los de las palabras integradas en un párrafo con ajuste de línea.
| Resultado previsto | Ajuste que probar | Qué comprobar |
|---|---|---|
| Mantener una línea de base compartida para el texto | Asignar al tramo pequeño un interlineado adecuado y hacer que las métricas de fuente del elemento padre coincidan con las del texto principal | Que el strut del elemento padre ya no aporte una extensión inferior no deseada |
| Alinear la parte superior de etiquetas separadas | Probar vertical-align: top en ambos tramos en línea |
Que la nueva relación entre las líneas de base se ajuste al diseño |
| Centrar etiquetas separadas en una fila | Usar un contenedor flex con align-items: center |
Que el comportamiento en anchos reducidos y el ajuste de los elementos sigan siendo adecuados para el diseño |
| Mantener el flujo continuo del párrafo | Conservar el texto en línea y usar valores deliberados de interlineado heredado | Que todas las líneas resultantes admitan el texto de tamaños mixtos |
vertical-align: top alinea un elemento y sus descendientes con la parte superior de la línea. middle tiene otra definición: alinea el punto medio del elemento con la línea de base del elemento padre más la mitad de la altura de la x del elemento padre. Por tanto, no significa centrado geométrico en toda la fila, y cambiar la alineación no garantiza una altura final concreta. MDN: Valores de vertical-align
Para dos etiquetas independientes, flexbox ofrece alineación explícita en el eje transversal mediante align-items. La alineación centrada y la alineación por la línea de base expresan decisiones de diseño distintas. Cambiar a flexbox modifica el contexto de diseño; úsalo cuando las etiquetas sean elementos independientes y evalúa el resultado en anchos más reducidos. MDN: align-items
Un interlineado menor también puede hacer que el texto se dibuje fuera del espacio que ocupa en el diseño. Comprueba las líneas contiguas después de reducir el espacio; una caja medida más compacta no demuestra por sí sola que el texto quepa sin solaparse. W3C: Interlineado y medio interlineado
¿Pueden las mediciones de canvas sustituir el diseño de líneas del navegador?
Las mediciones de canvas responden a una pregunta relacionada. WHATWG define measureText() y distingue las métricas de ascenso y descenso de la fuente de los límites reales del texto concreto. Estas mediciones son útiles para dibujar en canvas, pero la medición de los límites de la tinta no incorpora el strut del elemento padre del DOM, la alineación en línea ni las contribuciones al interlineado. No la uses por sí sola para predecir la altura de esta fila. WHATWG: TextMetrics
Conserva los límites del conformado de texto al hacer pruebas. CSS exige que el conformado continúe entre límites de elementos en línea cuando no hay un cambio efectivo de formato, mientras que ciertos límites —incluida la alineación vertical no inicial— requieren que el conformado se interrumpa. Evita envolver caracteres individuales para medirlos: dividir grupos de grafemas o ligaduras puede producir resultados incoherentes. Mantén intactas las etiquetas completas o las secuencias de texto con sentido. W3C: Procesamiento de texto y conformado entre límites de elementos
Para resolver la altura adicional, identifica qué elemento determina el extremo superior y cuál determina el inferior, incluido el elemento padre. Ajusta sus contribuciones al interlineado o elige el modelo de alineación que corresponda al propósito de las etiquetas; luego vuelve a medir la fila completa con el texto y la fuente previstos.
Fuentes
- Detalles del modelo de formato visual — W3C.
- Módulo de diseño en línea de CSS, nivel 3 — W3C.
- Propiedad CSS line-height — MDN Web Docs.
- Propiedad CSS vertical-align — MDN Web Docs.
- Descripción general de Chrome DevTools — Google for Developers.
- Referencia de funciones de CSS — Google for Developers.
- FontFaceSet: propiedad ready — MDN Web Docs.
- Element: método getBoundingClientRect() — MDN Web Docs.
- Propiedad CSS align-items — MDN Web Docs.
- Estándar HTML: Canvas — WHATWG.
- Módulo de texto de CSS, nivel 3 — W3C.