Pretext: Cómo medir y maquetar texto de alto rendimiento sin tocar el DOM

La mayoría de nosotros aceptamos que el navegador se encargue de todo: le das un <div>, un poco de CSS, y él decide dónde cortar las líneas. Pero, ¿qué pasa cuando necesitas un control milimétrico o cuando el rendimiento cae en picado porque tienes miles de nodos de texto?

Aquí entra Pretext, la librería experimental de Cheng Lou (uno de los creadores de ReasonML y figura clave en el ecosistema de React).

¿Qué hace a Pretext diferente?

  • Predecible: El texto se renderiza exactamente igual en cualquier entorno porque tú posees la lógica del layout.
  • Independencia del DOM: Realiza el cálculo de saltos de línea, anchos y alturas directamente en JavaScript/Reason.
  • Velocidad de vértigo: Al no depender de getBoundingClientRect() o de insertar elementos en el DOM para medir, evitas los fatídicos layout thrashing.

Por qué medir texto después de renderizar puede salir caro

El patrón habitual en muchos proyectos es este:

  1. renderizas el contenido,
  2. mides el nodo con el DOM,
  3. descubres que la altura no encaja,
  4. corriges el layout,
  5. y fuerzas un nuevo ciclo visual.

Cuando esto se repite mucho, empiezan los problemas:

  • cards que “bailan” al cargar,
  • rejillas que se reordenan tarde,
  • botones que quedan desalineados,
  • saltos visuales que rompen el ritmo de lectura,
  • y una sensación de interfaz inestable aunque “funcione”.

La propuesta de Pretext: calcular antes, no reaccionar después

La idea base de Pretext se puede resumir así:

si el sistema puede prever cómo se comportará el texto antes de pintar, la interfaz tiene menos que corregir después.

Y eso cambia bastante las reglas del juego. Pasas de un flujo reactivo como este:

render → medir → corregir → repaint

a uno más anticipatorio:

texto → cálculo → layout → render

Ese cambio, que sobre el papel puede parecer pequeño, tiene implicaciones enormes en componentes donde el texto condiciona la estructura visual.

Cómo funciona Pretext: prepare, layout y segmentación

La librería se apoya en una idea sencilla pero potente: separar el trabajo caro del trabajo frecuente.

prepare(): la fase pesada

La función prepare() se encarga del trabajo más costoso. Aquí se procesa el texto, se normaliza, se segmenta y se dejan listas estructuras que luego pueden reutilizarse.

La gracia está en que esta parte no deberías repetirla todo el rato si el contenido no ha cambiado. Es decir, si tienes el mismo excerpt pero cambia el ancho disponible, no necesitas reanalizar todo el texto desde cero una y otra vez.

layout(): la fase rápida

Después entra layout(), que calcula altura, líneas y distribución del contenido según el ancho disponible y el line-height que definas. Esta parte es mucho más ligera y es la que puedes reutilizar en resizes, layouts responsivos o cálculos previos al render.

Ejemplo conceptual básico

import { prepare, layout } from "@chenglou/pretext";

const excerpt = "Baseline no es soporte total: cómo tomar decisiones realistas en front-end sin sobredimensionar el soporte.";
const prepared = prepare(excerpt, '16px "Work Sans"');

const result = layout(prepared, 280, 24);

console.log(result.height);
console.log(result.lineCount);

Este patrón puede parecer pequeño, pero cambia por completo cómo diseñas ciertos componentes. Porque ya no estás esperando a ver qué decide el navegador una vez pintado el contenido: estás llegando al render con información previa.

Tiempo de decisión vs. carga cognitiva: por qué esta librería también importa en UX

Este punto es especialmente interesante porque aquí Pretext deja de ser solo una curiosidad técnica y se convierte en una herramienta útil para pensar diseño e interacción.

Cuando el texto cambia de tamaño tarde, cuando una tarjeta recoloca su contenido al terminar de calcular alturas o cuando un bloque empuja elementos hacia abajo en el último momento, el usuario tiene que rehacer parte de su lectura visual. Aunque ese esfuerzo sea mínimo, existe. Y cuando se acumula, genera fricción.

Por eso aquí encaja muy bien la comparación entre tiempo de decisión vs. carga cognitiva:

  • Sin control previo del layout: el sistema decide tarde, corrige tarde y el usuario interpreta más veces.
  • Con una estrategia más predictiva: el sistema reserva mejor el espacio y el usuario lee con menos interrupciones.

Una interfaz estable no solo “se ve mejor”. También reduce el número de microdecisiones que el usuario tiene que tomar para orientarse. Y eso tiene un impacto directo en comprensión, ritmo de lectura y sensación de calidad.

Esta relación también enlaza bien con temas como la accesibilidad en microinteracciones, donde pequeños cambios en el comportamiento visual o temporal pueden afectar muchísimo a cómo se percibe una interfaz.

Cuando la interfaz salta, el usuario paga el coste

Google lleva tiempo insistiendo en la importancia del CLS (Cumulative Layout Shift), precisamente porque los desplazamientos inesperados del contenido afectan a la calidad percibida. Si quieres profundizar en esa parte, merece la pena revisar la guía de web.dev sobre cómo optimizar los layout shifts y el CLS.

Pero más allá de la métrica, la idea importante es esta: cada corrección tardía del layout le pide algo al usuario. A veces es atención. A veces es paciencia. A veces es reinterpretación visual. Ninguna de esas tres cosas es gratis.

Ejemplos reales de diseño e interacción donde Pretext sí tiene sentido

No todas las interfaces necesitan esta librería. Y justo por eso conviene ver casos concretos donde sí aporta valor real.

Cards editoriales con excerpt variable

Este es probablemente uno de los escenarios más claros. Imagina un grid de posts con:

  • imagen destacada,
  • título con longitud variable,
  • excerpt de varias líneas,
  • y un CTA al final.

Si no controlas bien la altura del texto, el resultado suele ser el típico grid donde unas cards parecen “más largas” que otras, algunos botones quedan a distinta altura y el ritmo visual se rompe.

Con Pretext puedes calcular la altura del excerpt antes de renderizar y reservar un espacio más estable:

const prepared = prepare(post.excerpt, '16px "Work Sans"');
const { height } = layout(prepared, 280, 24);

Y luego usar esa altura en el componente para evitar correcciones tardías.

Ejemplo de uso en una card

function PostCard({ post }) {
  const prepared = prepare(post.excerpt, '16px "Work Sans"');
  const { height } = layout(prepared, 280, 24);

  return (
    <article className="post-card">
      <img src={post.image} alt={post.title} />
      <h2>{post.title}</h2>
      <p style={{ height: `${height}px`, overflow: "hidden" }}>
        {post.excerpt}
      </p>
      <a href={post.url}>Leer artículo</a>
    </article>
  );
}

Este tipo de planteamiento encaja especialmente bien si te interesan también temas de arquitectura y decisión técnica como los que aparecen en Primeros pasos con Astro o qué es Vanilla JS, porque al final todo esto forma parte de la misma conversación: qué merece abstraerse y qué merece resolverse con una aproximación más directa.

Masonry real sin hacks ni estimaciones pobres

Otro caso donde Pretext puede tener bastante sentido es en un masonry donde la altura de cada bloque depende del texto. Muchas implementaciones acaban mezclando:

  • mediciones del DOM,
  • ResizeObserver,
  • recolocaciones posteriores,
  • y pequeños glitches durante la carga.

Si puedes estimar mejor la altura del contenido antes de pintarlo, la distribución inicial de las piezas gana en estabilidad.

const baseHeight = 260;
const excerptHeight = layout(preparedExcerpt, 280, 24).height;
const finalCardHeight = baseHeight + excerptHeight;

Y a partir de ahí colocar cada tarjeta en la columna más baja sin esperar a renderizar primero para descubrir cuánto ocupa.

Textarea auto-resizable con menos fricción

Otro ejemplo muy útil es el de un textarea autoajustable. En muchos casos se resuelve leyendo scrollHeight, pero eso obliga a depender del nodo ya renderizado. Con Pretext, si respetas espacios y saltos de línea, puedes calcular mejor el crecimiento del texto sin ese paso reactivo.

const prepared = prepare(value, '16px Inter', {
  whiteSpace: "pre-wrap"
});

const { height } = layout(prepared, 400, 22);

No siempre será necesario, pero en herramientas de escritura, formularios largos o interfaces donde el texto tenga mucho peso, puede ser una solución bastante elegante.

Herramientas visuales y render en Canvas o SVG

Aquí es donde la librería se vuelve especialmente interesante para proyectos más creativos. Si estás construyendo composiciones tipográficas, generadores visuales, exportaciones a imagen o interfaces que no dependen de un flujo DOM tradicional, poder obtener líneas de texto manualmente es una ventaja enorme.

Si quieres ver esa parte más experimental, merece la pena echar un vistazo a las demos oficiales de Pretext, porque muestran bastante bien hacia dónde apunta la librería más allá del caso típico de una card.

Si quieres profundizar directamente en la fuente, lo mejor es ir al repositorio oficial de Pretext en GitHub.

Preguntas frecuentes sobre la librería Pretext (FAQs)

¿Pretext sustituye a React, Vue o Astro?

No. Pretext no compite con esos frameworks. Se usa junto a ellos cuando necesitas medir y predecir mejor el comportamiento del texto antes de renderizarlo.

¿Es mejor que resolverlo con CSS?

Depende del caso. Para layouts simples, CSS suele ser suficiente y más apropiado. Pretext empieza a tener sentido cuando la alternativa real implica mediciones del DOM, reflows, correcciones posteriores o una interfaz visualmente inestable.

¿Tiene sentido dentro de una estrategia Baseline-first?

Sí, pero no por defecto. Tiene sentido cuando sustituye una complejidad mayor por una solución más controlada. Si introduces la librería sin una necesidad real, probablemente no compense.


El futuro del texto como «Cálculo Matemático»

Para entender por qué Pretext es una genialidad técnica, hay que entender cómo funciona Internet hoy: normalmente, le damos el texto al navegador y este, como un decorador de interiores, decide sobre la marcha dónde «cortar» las frases para que quepan. Este proceso es cómodo, pero lento y a veces impredecible.

Pretext cambia las reglas del juego tratando el texto no como un elemento de diseño, sino como un problema matemático de alta precisión:

  • Adiós a la «adivinación» del navegador: En lugar de pedirle al navegador que mida el texto (un proceso pesado llamado Reflow), Pretext ya conoce las medidas exactas de cada letra de antemano. Es como si el decorador ya trajera los muebles cortados al milímetro en lugar de medirlos en la habitación.
  • Eficiencia algorítmica: Utiliza lógica inspirada en la tipografía de alta gama (como el algoritmo de Knuth-Plass). Esto no solo hace que el texto sea más eficiente de procesar, sino que busca la «belleza visual» de forma automática, evitando huecos extraños entre palabras que los navegadores normales suelen ignorar.
  • Velocidad de ejecución: Al mover todo este trabajo fuera de la vista del navegador y gestionarlo directamente en el motor de JavaScript, se eliminan los cuellos de botella. El resultado es una interfaz que responde de forma instantánea, incluso con volúmenes de datos que harían que una web normal se bloquease.

Pretext es una apuesta por el control absoluto. Nos demuestra que para alcanzar el siguiente nivel de rendimiento en la web, a veces debemos dejar de confiar en las herramientas automáticas del navegador y volver a los fundamentos de la computación: datos puros, cálculos exactos y renderizado inteligente.