El componente Font y el preload
La segunda mitad de la API de fuentes: el componente Font de astro:assets, que inyecta en el head las reglas @font-face y los enlaces de preload de una familia identificada por su cssVariable, cómo aplicarla en CSS con var, y el criterio para activar el preload sin penalizar el resto de recursos.
Declarar una familia en la configuración es solo la mitad del trabajo: describe qué fuente quieres, pero no la pone aún en la página. La otra mitad es emitir en el head del documento las reglas @font-face que apuntan a los archivos autoalojados y, opcionalmente, los enlaces de preload que adelantan su descarga. Ese es el oficio del componente <Font />, que Astro exporta desde astro:assets. Esta lección cierra el circuito: de la variable declarada en la config a la fuente pintada en pantalla.
- Importar e insertar
<Font />desdeastro:assetsen elheadde un layout. - Enlazar la etiqueta con una familia concreta mediante la prop
cssVariable. - Aplicar la fuente en tus estilos con
font-family: var(--...). - Activar
preloadcon criterio y entender por qué debe usarse con moderación.
Font: qué inyecta en el head
El componente se coloca en el head, casi siempre dentro del layout o de un componente Head dedicado, y recibe la cssVariable de la familia que quieres activar. Con eso le basta para saber qué reglas emitir.
---
// src/layouts/Base.astro
import { Font } from 'astro:assets';
---
<html lang="es">
<head>
<meta charset="utf-8" />
<Font cssVariable="--font-inter" />
</head>
<body>
<slot />
</body>
</html>
Lo que <Font /> escribe en el HTML no es magia, sino exactamente las etiquetas que habrías tenido que redactar a mano, pero derivadas de tu configuración y apuntando a los archivos que Astro ya descargó y optimizó. Una regla @font-face por cada variante, con su src local, y la definición de la variable CSS con la pila de fallbacks resuelta.
<!-- salida aproximada que genera el componente -->
<style>
@font-face {
font-family: 'Inter';
src: url('/_astro/inter-400.abc123.woff2') format('woff2');
font-weight: 400;
font-display: swap;
}
:root { --font-inter: 'Inter', 'Inter fallback', sans-serif; }
</style>
Repara en el detalle: la variable --font-inter no contiene solo el nombre de la fuente, sino una pila completa que incluye la fuente real, un respaldo optimizado y una familia genérica. Ese es el valor que tu CSS consumirá, y por eso te basta con nombrarlo para heredar toda la estrategia de carga y respaldo que Astro montó por ti.
Aplicar la fuente por CSS
Con la etiqueta en el head, la fuente está disponible pero aún no se usa: Astro no decide por ti qué elementos la llevan. Esa elección es tuya, y la haces en CSS refiriéndote a la variable, ya sea en un bloque <style> con ámbito de componente o en tu hoja global.
<h1>Titular con fuente propia</h1>
<p>Este párrafo usa la fuente del sistema.</p>
<style>
h1 { font-family: var(--font-inter); }
</style>
La separación es deliberada y valiosa. El componente <Font /> se ocupa de que la fuente exista y se cargue bien; el CSS se ocupa de dónde se aplica. Puedes tener varias familias activas en el head y repartirlas con precisión, una para titulares, otra para el cuerpo, otra para el código, sin que ninguna se imponga donde no la quieres. La variable es el punto de encuentro entre ambas responsabilidades.
Cuando escribes font-family: var(--font-inter), no estás fijando una única fuente: estás desplegando la pila entera que Astro definió, con su respaldo métrico y su genérica final. Por eso nunca deberías añadir tu propia lista de fallbacks a mano detrás de la variable; duplicarías lo que la API ya resolvió mejor que tú, y podrías anular el respaldo optimizado que evita los saltos de maquetación.
preload: coste y criterio
Por defecto, <Font /> emite las reglas @font-face pero no fuerza la descarga anticipada: el navegador buscará la fuente cuando la encuentre necesaria al aplicar los estilos. La prop preload cambia eso, añadiendo un <link rel="preload"> que le dice al navegador que empiece a bajar la fuente cuanto antes.
<head>
<Font cssVariable="--font-inter" preload />
</head>
Adelantar la descarga suena siempre bueno, pero no lo es. Un preload compite por el ancho de banda con todo lo demás que la página necesita para el primer pintado, y precargar una fuente que no aparece en la parte visible inicial roba prioridad a recursos que sí importan.
Si una familia tiene varias variantes, puedes afinar aún más pasando un arreglo a preload en vez de un booleano, para adelantar solo el archivo concreto que hace falta arriba del pliegue y dejar los demás a demanda. Así precargas, por ejemplo, el peso regular que domina el cuerpo del texto sin arrastrar contigo la negrita o la cursiva, que el navegador ya buscará si aparecen.
<head>
<!-- precarga selectiva: solo el archivo que se ve al inicio -->
<Font
cssVariable="--font-inter"
preload={[{ weight: 400, style: 'normal' }]}
/>
</head>
La regla general es de contención: cada byte que precargas es un byte que le quitas a otra cosa. La precarga bien usada es un bisturí, no una manta.
El preload es un recurso escaso, no un ajuste que se activa en todo. Reserva la precarga para la fuente crítica que se ve en el primer viewport, típicamente la del cuerpo de texto o la del titular principal, y no para las secundarias. Precargar de más invierte el efecto que buscas: en lugar de acelerar el contenido importante, lo retrasas obligando al navegador a repartir su atención entre demasiadas descargas urgentes a la vez.
Si quieres que una familia sea la del documento entero, aplica su variable en el selector body de tu hoja global: body { font-family: var(--font-inter); }. Como las propiedades personalizadas se heredan por la cascada, toda la página adoptará la fuente salvo donde la sobrescribas. Es el patrón habitual para la tipografía de cuerpo, mientras reservas variables distintas para titulares o monospaciadas puntuales.
flowchart TD
FONT[Font con cssVariable en el head] --> FACE[emite reglas font face]
FONT --> PL{prop preload activa}
PL -->|no| DEM[el navegador baja la fuente al aplicar el CSS]
PL -->|si| LINK[anade link rel preload]
LINK --> EARLY[descarga adelantada de la fuente critica]
FACE --> CSS[var en font family aplica la fuente]
style FONT fill:#89b4fa,color:#11111b
style CSS fill:#a6e3a1,color:#11111bFont
Se coloca en el head. Recibe la cssVariable y emite las reglas y enlaces de esa familia.
cssVariable
Identifica que familia activar. Es el mismo nombre que declaraste en la config.
var en CSS
Aplicas la fuente donde quieras con font-family: var(--...). Tu decides el alcance.
preload
Adelanta la descarga de la fuente critica. Usalo solo para lo visible al inicio.
Merece la pena detenerse en por qué la API se parte en dos piezas, la declaración en la config y el componente en el head, en vez de resolverlo todo en un único lugar. La razón es una separación de responsabilidades que recorre todo Astro: la configuración describe qué fuentes forman parte de tu sistema, una verdad estable y global; el componente decide dónde y cómo se manifiestan esas fuentes en un documento concreto, una cuestión local y contextual. Al mantenerlas separadas, la misma familia declarada una vez puede activarse en unos layouts y omitirse en otros, precargarse en las páginas donde es crítica y dejarse a demanda donde no lo es, sin tocar jamás su definición. El componente <Font /> es, en el fondo, una proyección: toma la intención abstracta que vive en la config y la materializa como etiquetas reales en el punto exacto del documento donde tú lo colocas. Este es el mismo patrón que ya viste en el head centralizado del layout, donde la página aporta unos datos y la plantilla los proyecta en decenas de metaetiquetas, y lo reconocerás una y otra vez en frameworks bien diseñados: separar la declaración de la intención de su emisión concreta permite que una sola fuente de verdad se exprese de mil formas distintas según el contexto, sin duplicarse ni contradecirse. Cuando entiendes que <Font /> no configura nada, sino que emite lo ya configurado, dejas de verlo como un botón que enciende una fuente y empiezas a verlo como el lugar donde una decisión global se vuelve HTML concreto.
- Importa
<Font />desdeastro:assetsy colócalo en elheadde tu layout con lacssVariablede una familia que hayas declarado. - Inspecciona el HTML generado y localiza las reglas
@font-facey la definición de la variable con su pila de fallbacks. - Aplica la fuente solo a los
h1confont-family: var(--...)y verifica que los párrafos siguen con la fuente del sistema. - Activa
preloaden la fuente del titular, mide el primer pintado con y sin él, y razona si esa precarga se justifica para tu página.