Optimización de fuentes web con Claude Code
Guía práctica para optimizar fuentes web con Claude Code: preload, font-display, subsetting, CLS/LCP y verificación.
La optimización de fuentes es un problema de renderizado
Las fuentes web suelen tratarse como una decisión de marca, pero en producción también son una decisión de rendimiento. Una fuente lenta puede dejar el texto invisible, cambiar el ancho de un titular después de que el usuario empezó a leer, mover un botón de compra o empeorar el LCP. LCP significa Largest Contentful Paint: el tiempo hasta que se pinta el elemento de contenido más grande del primer viewport. CLS significa Cumulative Layout Shift: movimiento inesperado del layout durante la carga.
En idiomas con muchos caracteres, como japonés, chino o coreano, el problema es todavía más visible. Un solo archivo de fuente puede pesar más que todo el CSS crítico. Por eso Claude Code no debe recibir una orden vaga como “optimiza las fuentes”. Necesita una estrategia: qué fuente es crítica, qué archivo se precarga, qué texto puede usar una fuente del sistema, cómo se evita CLS y cómo se verifica con datos.
Esta guía usa un sitio Astro como ejemplo. Cubre estrategia de carga, preload, preconnect, font-display, fuentes variables, subsetting, self-host frente a proveedores externos, riesgos de CLS/LCP, revisiones estilo Lighthouse y WebPageTest, y prompts seguros para implementar con Claude Code. Para los detalles del navegador, usa la documentación oficial de MDN sobrefont-display yrel="preload". Para la visión general, consulta web.dev sobremejores prácticas de fuentes, optimización de web fonts yWeb Vitals.
Define la estrategia antes de tocar código
El primer paso es decidir qué texto merece presupuesto de red en el primer viewport. Si todo se marca como crítico, nada es realmente crítico. En un blog, el cuerpo puede empezar con fuentes del sistema y reservar la fuente de marca para titulares. En un panel SaaS, una fuente variable latina puede cubrir etiquetas, tablas y botones. En una landing page, el titular del hero y la imagen compiten por el LCP, así que no conviene precargar todos los pesos.
| Caso de uso | Estrategia recomendada | Motivo | Fallo común |
|---|---|---|---|
| Blog multilingüe | Cuerpo con fuente del sistema, titulares con fuente web subset | El contenido se lee aunque la fuente tarde | La fuente decorativa termina aplicada al cuerpo |
| Dashboard SaaS | Fuente variable self-host para UI | Un archivo cubre varios pesos | Se incluyen cursivas, ejes o idiomas no usados |
| Landing page | Preload solo del WOFF2 usado por el titular LCP | El mensaje principal aparece antes | Todos los pesos compiten con la imagen hero |
| Icon font heredada | Sustituir por SVG o librería de iconos | Elimina una petición de fuente | Se rompe CSS con pseudo-elementos |
Para decidir el orden de impacto, revisa también laguía de optimización de imágenes con Claude Code, porque imagen hero y fuente de titular suelen competir. Si el objetivo es mejorar todo el sitio, conecta este trabajo con laoptimización de performance con Claude Code.
Implementa preload y preconnect en Astro
preload es una pista fuerte para el navegador. Úsala solo para uno o dos archivos WOFF2 que se usen realmente en el primer viewport. No precargues todos los pesos ni todas las variantes idiomáticas. Si las fuentes están en tu propio origen, normalmente no necesitas preconnect. Si usas Google Fonts u otro proveedor, sí puede tener sentido preconectar con el dominio de CSS y el dominio de archivos de fuente.
---
// src/layouts/BaseLayout.astro
const criticalFonts = [
{ href: "/fonts/inter-var-latin.woff2", type: "font/woff2" },
{ href: "/fonts/noto-sans-jp-latin-kana.woff2", type: "font/woff2" },
];
const usesGoogleFonts = false;
---
<html lang="es">
<head>
{criticalFonts.map((font) => (
<link rel="preload" href={font.href} as="font" type={font.type} crossorigin />
))}
{usesGoogleFonts && <link rel="preconnect" href="https://fonts.googleapis.com" />}
{usesGoogleFonts && <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />}
<link rel="stylesheet" href="/styles/fonts.css" />
</head>
<body>
<slot />
</body>
</html>
Después de generar el HTML, comprueba tres cosas. El href del preload debe coincidir con el src de @font-face. La etiqueta debe tener as="font", type="font/woff2" y crossorigin. Además, la fuente precargada debe usarse pronto. Si Chrome indica que se precargó un recurso no utilizado, quita esa pista.
Usa font-display sin crear CLS
font-display: swap muestra primero una fuente de reserva y luego cambia a la fuente web cuando llega. Es útil para evitar texto invisible, pero puede mover el layout si las métricas no coinciden. font-display: optional puede ser mejor para texto no crítico en redes lentas, porque el navegador puede conservar la fuente de reserva.
/* public/styles/fonts.css */
@font-face {
font-family: "InterVariable";
src: url("/fonts/inter-var-latin.woff2") format("woff2");
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "NotoSansJPSubset";
src: url("/fonts/noto-sans-jp-latin-kana.woff2") format("woff2");
font-weight: 400 700;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF, U+3000-30FF, U+FF00-FFEF;
}
@font-face {
font-family: "InterFallback";
src: local("Arial");
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
:root {
--font-ui: "InterVariable", "InterFallback", system-ui, sans-serif;
--font-ja: "NotoSansJPSubset", "Hiragino Sans", "Yu Gothic", sans-serif;
}
body {
font-family: var(--font-ui);
}
article {
font-family: var(--font-ja);
}
El descriptorunicode-range permite aplicar una fuente solo a ciertos caracteres. No reduce el archivo por sí solo. Para reducir bytes, necesitas generar un WOFF2 más pequeño.
Reduce bytes con fuentes variables y subsetting
Una fuente variable puede sustituir varios archivos estáticos cuando necesitas muchos pesos. Aun así, no siempre es más ligera. Si trae muchos ejes, cursivas y rangos de idioma que no usas, puede seguir siendo costosa. Pide a Claude Code que audite pesos reales, familias usadas y rutas CSS antes de cambiar la implementación.
El subsetting consiste en crear un archivo de fuente con solo los caracteres necesarios. Funciona muy bien para navegación, titulares hero, etiquetas fijas y CTA. Es más delicado para artículos, porque cada publicación nueva puede introducir caracteres no incluidos.
# Create a WOFF2 subset with Latin, punctuation, kana, and full-width forms.
python -m pip install "fonttools[woff]"
mkdir -p public/fonts
pyftsubset ./vendor-fonts/NotoSansJP-Regular.ttf \
--output-file=./public/fonts/noto-sans-jp-latin-kana.woff2 \
--flavor=woff2 \
--layout-features='*' \
--unicodes="U+0000-00FF,U+3000-30FF,U+FF00-FFEF"
Este ejemplo no cubre la mayoría de kanji. Sirve para navegación y titulares, no para un cuerpo de artículo japonés completo. Si quieres cubrir el cuerpo, extrae caracteres reales desde los MDX y usa --text-file, o genera un subset separado. También revisa la licencia: algunas fuentes permiten self-host, otras no permiten modificación o redistribución.
Self-host o proveedor externo
Self-host significa servir los archivos desde tu propio dominio. Ganas control sobre URLs, cache, fingerprints, preload y subsetting. A cambio, debes gestionar licencia, actualizaciones y scripts. Un proveedor externo como Google Fonts es rápido para empezar, pero añade conexiones externas y una petición CSS antes del archivo de fuente.
| Criterio | Self-host | Tercero |
|---|---|---|
| Conexión inicial | Mismo origen | DNS, TLS, CSS externo y origen de fuente |
| Cache | Control completo | Depende del proveedor |
| Preload | Apunta al WOFF2 exacto | El CSS puede decidir la URL |
| Subsetting | Flexible | Depende de la API |
| Operación | Más responsabilidad | Más cómodo, más dependencia |
Para páginas sensibles a conversión, suele ser mejor self-host para fuentes críticas y carga diferida para fuentes decorativas. En prototipos, un proveedor externo está bien si cargas solo pesos usados, usas display=swap y evitas duplicar la misma familia desde dos lugares.
Verifica con Lighthouse y una cascada estilo WebPageTest
Tras implementar, revisa el orden de red. Lighthouse da una señal de laboratorio sobre LCP, CLS y avisos de fuentes. Luego mira una cascada como harías en WebPageTest: HTML, CSS, fuente crítica, imagen hero y JavaScript. La fuente debe empezar pronto, pero no bloquear el CSS ni competir innecesariamente con el elemento LCP.
URL="https://example.com/"
npx --yes lighthouse "$URL" \
--only-categories=performance \
--chrome-flags="--headless" \
--output=json \
--output-path=./lighthouse-fonts.json
node -e "const r=require('./lighthouse-fonts.json'); for (const id of ['largest-contentful-paint','cumulative-layout-shift','font-display']) console.log(id, r.audits[id]?.displayValue ?? r.audits[id]?.score ?? 'n/a')"
Revisa estos puntos: solo una o dos fuentes críticas empiezan temprano; no hay aviso de preload no usado; la visita repetida usa cache; el titular y el CTA no se mueven durante el swap; no queda CSS de Google Fonts si ya migraste a self-host; no se descarga el mismo WOFF2 dos veces.
Los fallos típicos son concretos. Se precarga una negrita que no aparece en el primer viewport. El subset elimina signos de puntuación, dígitos de ancho completo o caracteres largos. El equipo añade font-display: swap pero no ajusta métricas de fallback. La fuente de iconos sigue cargándose aunque los iconos ya se migraron a SVG.
Prompts seguros para Claude Code
Divide el trabajo en auditoría, implementación y verificación. Empieza sin permitir edición.
Audit web font loading in this Astro site. Do not edit files yet.
Find:
- @font-face, Google Fonts, Fontsource, and CSS import locations
- Font files used above the fold
- preload and preconnect hints that are missing or unnecessary
- CLS or LCP risks caused by font swapping
- Candidates for self-hosting, variable fonts, and subsetting
Return:
- A prioritized table of changes
- Files that should be edited and files that must not be touched
- Verification commands and residual risks
Luego limita el alcance de implementación.
Implement web font optimization only in these files:
- src/layouts/BaseLayout.astro
- public/styles/fonts.css
- generated files under public/fonts/
Acceptance criteria:
- Preload only WOFF2 files used in the first viewport
- Do not add preconnect when fonts are self-hosted
- Every @font-face has a deliberate font-display value
- Fallback metrics are adjusted to reduce CLS
- Existing routes, article slugs, hero images, and unrelated content are untouched
Verification:
- npm run build
- node scripts/check-code-fences.mjs
- Lighthouse check for LCP, CLS, and font-display
- Report what could not be verified
Resultado práctico y CTA
En el flujo de Masa, la instrucción específica funcionó mejor que la genérica. “Precarga solo la fuente del titular LCP, deja el cuerpo legible con fuentes del sistema y reporta riesgo de CLS” produjo cambios pequeños y revisables. En una página japonesa, un subset latino y kana hizo más estable el primer viewport, pero cubrir todo el cuerpo exigió extracción de caracteres. La verificación más útil fue una cascada móvil lenta y una revisión manual del titular y del CTA durante el cambio de fuente.
Para llevar esto a un equipo, documenta reglas de fuentes en CLAUDE.md. Empieza con lachuleta gratuita para comandos seguros, usa lasplantillas de productos para prompts repetibles y considera laformación de Claude Code si quieres mejorar Core Web Vitals, calidad editorial y CTA de monetización al mismo tiempo.
Autochequeo antes de publicar: el artículo incluye más de tres casos de uso, ejemplos Astro/CSS/bash copiables, enlaces oficiales a MDN y web.dev, enlaces internos, errores concretos, CTA natural y nota de verificación práctica.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Permission receipt para Claude Code: alcance, prueba y rollback
Patrón de permission receipt para Claude Code: acciones permitidas, aprobación, pruebas, rollback y CTA de ingresos.
Agent Harness seguro para Claude Code y Codex: permisos, verificacion y rollback
Diseña un Agent Harness seguro para Claude Code y Codex con permisos, plan, verificaciones y rollback.
Subagentes de Claude Code: guía práctica para delegar trabajo de forma segura
Guía práctica de subagentes en Claude Code para dividir artículos y código: reglas, prompts, riesgos y checklist.