Documentación de UXR SEO Analyzer

Introducción

Carga de Fuentes

Ver contenido

Introducción

Las fuentes web permiten a los diseñadores ir más allá de las fuentes del sistema, creando experiencias de marca únicas. Sin embargo, las fuentes son recursos que bloquean el renderizado—el navegador debe descargar y procesar los archivos de fuentes antes de mostrar el texto que las usa. Una carga de fuentes mal optimizada puede causar texto invisible (FOIT), cambios de layout y puntuaciones degradadas en Core Web Vitals.

Entender cómo los navegadores manejan la carga de fuentes es esencial para equilibrar el diseño visual con el rendimiento.

Cómo los Navegadores Cargan Fuentes Web

Cuando un navegador encuentra texto que usa una fuente personalizada, sigue un proceso específico:

Línea de Tiempo de Carga de Fuentes:
┌─────────────────────────────────────────────────────────────┐
│ 1. Navegador analiza CSS, descubre declaración @font-face   │
│    └── Comienza descarga de fuente (si font-display lo      │
│        permite)                                              │
│                                                             │
│ 2. Navegador necesita renderizar texto con esa fuente       │
│    └── Por defecto: Espera la fuente (FOIT - Flash of       │
│        Invisible Text)                                       │
│                                                             │
│ 3. Descarga de fuente completada                            │
│    └── Texto se renderiza con fuente personalizada          │
│                                                             │
│ 4. Descarga de fuente falla o timeout (~3 segundos)         │
│    └── Se muestra fuente de respaldo                        │
└─────────────────────────────────────────────────────────────┘

FOIT vs FOUT

Dos términos describen la experiencia visual durante la carga de fuentes:

Término Significado Experiencia de Usuario
FOIT Flash of Invisible Text Texto oculto hasta que carga la fuente (comportamiento por defecto)
FOUT Flash of Unstyled Text Fuente de respaldo mostrada primero, luego cambia cuando carga la personalizada

¿Cuál es mejor? Generalmente, FOUT es preferido para rendimiento porque los usuarios pueden leer el contenido inmediatamente, aunque el estilo cambie ligeramente cuando carga la fuente personalizada.

La Propiedad font-display

CSS proporciona font-display para controlar cómo los navegadores manejan la carga de fuentes:

@font-face {
  font-family: 'Fuente Personalizada';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap; /* Controla el comportamiento de carga */
}

Valores de font-display

Valor Comportamiento Mejor Para
auto El navegador decide (usualmente FOIT) No recomendado
block FOIT corto (~3s), luego respaldo Solo fuentes de iconos
swap Respaldo inmediato, intercambio cuando está lista Texto del cuerpo, títulos
fallback FOIT muy corto (~100ms), ventana de intercambio limitada Enfoque equilibrado
optional FOIT muy corto, puede omitir la fuente completamente Fuentes no críticas

Recomendación: Usa font-display: swap para la mayoría del texto para asegurar que el contenido siempre sea legible.

Impacto en Core Web Vitals

La carga de fuentes afecta múltiples métricas de rendimiento:

Métrica Cómo la Afectan las Fuentes
LCP Si el elemento LCP usa fuente personalizada, el texto invisible retrasa la medición del LCP
CLS El intercambio de fuentes puede causar cambios de layout si las fuentes de respaldo y personalizadas tienen tamaños diferentes
FCP El texto bloqueado retrasa el First Contentful Paint

La Conexión con LCP

Si tu elemento de contenido más grande es texto usando una fuente personalizada:

Sin font-display: swap
├── Solicitud de fuente inicia: 0ms
├── Texto invisible (FOIT): 0-2500ms
├── Fuente carga, texto aparece: 2500ms
└── LCP registrado: 2500ms ❌ Malo

Con font-display: swap
├── Solicitud de fuente inicia: 0ms
├── Texto de respaldo visible: 50ms
├── FCP registrado: 50ms ✅
├── Fuente carga, texto cambia: 2500ms
└── LCP registrado: 50ms ✅ Bueno (texto era visible antes)

Formatos Modernos de Fuentes

No todos los formatos de fuentes son iguales. Los formatos modernos ofrecen mejor compresión:

Formato Compresión Soporte de Navegadores Recomendación
WOFF2 Mejor (~30% menor que WOFF) 97%+ Formato principal
WOFF Buena 99%+ Solo como respaldo
TTF/OTF Ninguna Universal Evitar para web
EOT Moderada Solo IE Solo legacy

Mejor Práctica: Sirve WOFF2 como formato principal con WOFF como respaldo:

@font-face {
  font-family: 'Fuente Personalizada';
  src: url('/fonts/custom.woff2') format('woff2'),
       url('/fonts/custom.woff') format('woff');
  font-display: swap;
}

Problemas Comunes de Carga de Fuentes

Problema 1: Demasiados Archivos de Fuentes

Problema: Cargar múltiples pesos y estilos (regular, negrita, itálica, negrita-itálica) multiplica el tamaño de descarga.

Solución: Limita a 2-3 archivos de fuentes. Usa font-synthesis para pesos faltantes si es aceptable.

Problema 2: Sin font-display

Problema: El comportamiento por defecto del navegador causa texto invisible.

Solución: Siempre especifica font-display: swap (o fallback para fuentes no críticas).

Problema 3: Descubrimiento Tardío

Problema: El navegador descubre la necesidad de la fuente solo al analizar el CSS.

Solución: Precarga fuentes críticas en <head>:

<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>

Problema 4: Servicios de Fuentes de Terceros

Problema: Google Fonts u otros servicios agregan búsquedas DNS y conexiones adicionales.

Solución: Auto-hospeda las fuentes para mejor rendimiento, o usa preconnect:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

Midiendo el Rendimiento de Fuentes

Usando Chrome DevTools

  1. Abre DevTools → pestaña Network
  2. Filtra por “Font”
  3. Revisa tamaños de archivo y tiempos de carga
  4. Busca fuentes que bloquean el renderizado

Usando Lighthouse

Ejecuta una auditoría de Lighthouse y busca:

  • “Ensure text remains visible during webfont load”
  • “Preload key requests” (para fuentes críticas)
  • “Avoid enormous network payloads” (tamaños de archivos de fuentes)

Implementación

Estrategia 1: Optimizar Declaraciones @font-face

Sintaxis Completa de @font-face

@font-face {
  font-family: 'Fuente Marca';
  src: url('/fonts/brand-regular.woff2') format('woff2'),
       url('/fonts/brand-regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6;
}

@font-face {
  font-family: 'Fuente Marca';
  src: url('/fonts/brand-bold.woff2') format('woff2'),
       url('/fonts/brand-bold.woff') format('woff');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6;
}

Descriptores Clave Explicados

Descriptores de @font-face:
┌─────────────────────────────────────────────────────────────┐
│ font-family     │ Nombre para referenciar en CSS            │
│ src             │ URLs de archivos con hints de formato     │
│ font-weight     │ Peso numérico (100-900) o palabras clave  │
│ font-style      │ normal, italic, oblique                   │
│ font-display    │ Comportamiento de carga (swap recomendado)│
│ unicode-range   │ Subconjunto de caracteres a descargar     │
│ font-stretch    │ Variante de ancho (condensed, expanded)   │
│ size-adjust     │ Ajustar métricas para coincidir respaldo  │
│ ascent-override │ Ajuste fino de altura de línea            │
│ descent-override│ Ajuste fino de línea base                 │
└─────────────────────────────────────────────────────────────┘

Estrategia 2: Implementar font-display Correctamente

Elegir el Valor Correcto

/* Para texto del cuerpo - priorizar legibilidad */
@font-face {
  font-family: 'Fuente Cuerpo';
  src: url('/fonts/body.woff2') format('woff2');
  font-display: swap; /* Mostrar respaldo inmediatamente */
}

/* Para títulos - enfoque equilibrado */
@font-face {
  font-family: 'Fuente Titulo';
  src: url('/fonts/heading.woff2') format('woff2');
  font-display: fallback; /* FOIT breve, luego respaldo */
}

/* Para texto decorativo/no crítico */
@font-face {
  font-family: 'Fuente Decorativa';
  src: url('/fonts/decorative.woff2') format('woff2');
  font-display: optional; /* Puede no cargar en conexiones lentas */
}

/* Para fuentes de iconos - breve invisibilidad aceptable */
@font-face {
  font-family: 'Iconos';
  src: url('/fonts/icons.woff2') format('woff2');
  font-display: block; /* Iconos no deben mostrar respaldo */
}

Visualización de Línea de Tiempo de font-display

font-display: swap
├── 0ms: Solicitar fuente
├── 0ms: Mostrar respaldo inmediatamente
├── Fuente carga: Cambiar a fuente personalizada
└── Ventana de intercambio infinita

font-display: fallback
├── 0ms: Solicitar fuente
├── ~100ms: Período FOIT (invisible)
├── ~100ms: Mostrar respaldo si fuente no está lista
├── ~3s: Ventana de intercambio termina
└── Después de 3s: Mantener respaldo aunque cargue fuente

font-display: optional
├── 0ms: Solicitar fuente
├── ~100ms: Período FOIT (invisible)
├── ~100ms: Mostrar respaldo O fuente personalizada
└── Sin intercambio tardío - lo que se muestra permanece

Estrategia 3: Precargar Fuentes Críticas

Precarga Básica

<head>
  <!-- Precargar fuentes críticas ANTES del CSS -->
  <link
    rel="preload"
    href="/fonts/body-regular.woff2"
    as="font"
    type="font/woff2"
    crossorigin
  >
  <link
    rel="preload"
    href="/fonts/heading-bold.woff2"
    as="font"
    type="font/woff2"
    crossorigin
  >

  <!-- CSS que usa estas fuentes -->
  <link rel="stylesheet" href="/styles/main.css">
</head>

Reglas Importantes de Precarga

Mejores Prácticas de Precarga:
┌─────────────────────────────────────────────────────────────┐
│ ✅ HACER                                                     │
│ ├── Precargar fuentes usadas above the fold                 │
│ ├── Incluir `crossorigin` incluso para fuentes same-origin  │
│ ├── Especificar `type` para hints de formato                │
│ ├── Limitar a 2-3 fuentes críticas máximo                   │
│ └── Colocar preload antes de links de stylesheet            │
│                                                             │
│ ❌ NO HACER                                                  │
│ ├── Precargar todas las fuentes (desperdicia ancho de banda)│
│ ├── Olvidar crossorigin (causa descarga doble)              │
│ ├── Precargar fuentes no usadas en página actual            │
│ └── Precargar WOFF si el navegador soporta WOFF2            │
└─────────────────────────────────────────────────────────────┘

Precarga Condicional con JavaScript

// Solo precargar si fuente no está en caché
if (!sessionStorage.getItem('fontsLoaded')) {
  const preloadLink = document.createElement('link');
  preloadLink.rel = 'preload';
  preloadLink.as = 'font';
  preloadLink.type = 'font/woff2';
  preloadLink.crossOrigin = 'anonymous';
  preloadLink.href = '/fonts/body.woff2';
  document.head.appendChild(preloadLink);
}

Estrategia 4: Auto-Hospedar Fuentes

Por Qué Auto-Hospedar es Mejor

Aspecto Google Fonts Auto-Hospedado
DNS Lookup Lookup extra requerido Ninguno (mismo origen)
Conexión Nueva conexión a fonts.gstatic.com Reutiliza existente
Caché Caché compartida eliminada en Chrome Tus headers de caché
Control Limitado a sus opciones Control total
Privacidad Envía datos de usuario a Google Sin datos a terceros

Convertir Google Fonts a Auto-Hospedado

# Paso 1: Descargar fuentes usando google-webfonts-helper
# Visitar: https://gwfh.mranftl.com/fonts

# Paso 2: Elegir formatos (WOFF2 + WOFF recomendado)

# Paso 3: Descargar y extraer a directorio /fonts/

# Paso 4: Copiar CSS generado o crear el tuyo:
/* Fuente Inter auto-hospedada */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-regular.woff2') format('woff2'),
       url('/fonts/inter-regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-600.woff2') format('woff2'),
       url('/fonts/inter-600.woff') format('woff');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

Estrategia 5: Subconjuntos de Fuentes

Por Qué Importan los Subconjuntos

Fuente Completa vs Subconjunto:
┌─────────────────────────────────────────────────────────────┐
│ Roboto Regular Completa:                                    │
│ ├── Todos los caracteres latinos                            │
│ ├── Todos los caracteres cirílicos                          │
│ ├── Todos los caracteres griegos                            │
│ ├── Todos los caracteres vietnamitas                        │
│ └── Total: ~150 KB                                          │
│                                                             │
│ Subconjunto Solo Latino:                                    │
│ ├── Solo caracteres latinos                                 │
│ └── Total: ~20 KB (¡87% menor!)                            │
└─────────────────────────────────────────────────────────────┘

Usando unicode-range

/* Solo descargar caracteres latinos */
@font-face {
  font-family: 'Roboto';
  src: url('/fonts/roboto-latin.woff2') format('woff2');
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC,
                 U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
                 U+FEFF, U+FFFD;
}

/* Archivo separado para cirílico (solo descargado si es necesario) */
@font-face {
  font-family: 'Roboto';
  src: url('/fonts/roboto-cyrillic.woff2') format('woff2');
  font-display: swap;
  unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

Crear Subconjuntos con Herramientas

# Usando pyftsubset (fonttools)
pip install fonttools brotli

# Crear subconjunto latino
pyftsubset "Roboto-Regular.ttf" \
  --unicodes="U+0000-00FF,U+0131,U+0152-0153" \
  --layout-features="*" \
  --flavor="woff2" \
  --output-file="roboto-latin.woff2"

# Usando glyphhanger (npm)
npx glyphhanger https://tusitio.com --subset="*.ttf" --formats=woff2

Estrategia 6: Minimizar Layout Shift por Fuentes

Usando size-adjust y Overrides de Métricas

/* Coincidir métricas de respaldo con fuente personalizada */
@font-face {
  font-family: 'Fuente Custom';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap;
  /* Ajusta estos valores para coincidir con tu fuente de respaldo */
  size-adjust: 105%;
  ascent-override: 95%;
  descent-override: 22%;
  line-gap-override: 0%;
}

/* Definir stack de respaldo coincidente */
body {
  font-family: 'Fuente Custom', -apple-system, BlinkMacSystemFont,
               'Segoe UI', sans-serif;
}

Usando @font-face para Ajuste de Respaldo

/* Crear respaldo ajustado */
@font-face {
  font-family: 'Arial Ajustada';
  src: local('Arial');
  size-adjust: 105.5%;
  ascent-override: 100%;
  descent-override: 20%;
}

/* Usar respaldo ajustado en stack */
body {
  font-family: 'Fuente Custom', 'Arial Ajustada', sans-serif;
}

Encontrar Valores Correctos de Override

Usa herramientas como:

Estrategia 7: Fuentes Variables

Beneficios de Fuentes Variables

Fuentes Tradicionales vs Variable:
┌─────────────────────────────────────────────────────────────┐
│ Tradicional (4 pesos):                                      │
│ ├── Regular:    25 KB                                       │
│ ├── Medium:     26 KB                                       │
│ ├── Semibold:   26 KB                                       │
│ ├── Bold:       27 KB                                       │
│ └── Total:      104 KB (4 archivos, 4 solicitudes)         │
│                                                             │
│ Fuente Variable:                                            │
│ └── Todos los pesos: 70 KB (1 archivo, 1 solicitud)        │
│                                                             │
│ Ahorro: 34 KB + 3 solicitudes                               │
└─────────────────────────────────────────────────────────────┘

Implementar Fuentes Variables

@font-face {
  font-family: 'Inter Variable';
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-weight: 100 900; /* Rango de peso */
  font-stretch: 75% 125%; /* Rango de ancho (si está soportado) */
  font-style: oblique 0deg 10deg; /* Rango de inclinación */
  font-display: swap;
}

/* Usar cualquier peso dentro del rango */
h1 { font-weight: 750; }
h2 { font-weight: 650; }
p { font-weight: 400; }
strong { font-weight: 600; }

Estrategia 8: Patrón de Carga de Fuentes Críticas

FOFT (Flash of Faux Text)

/* Etapa 1: Solo romana (más rápido) */
@font-face {
  font-family: 'LatoInicial';
  src: url('/fonts/lato-regular.woff2') format('woff2');
  font-display: swap;
  unicode-range: U+0041-005A, U+0061-007A; /* A-Z, a-z */
}

/* Etapa 2: Fuente completa (carga después) */
@font-face {
  font-family: 'Lato';
  src: url('/fonts/lato-full.woff2') format('woff2');
  font-display: swap;
}
// Mejora progresiva
document.fonts.ready.then(() => {
  document.documentElement.classList.add('fonts-loaded');
});
/* Usar subconjunto inicial primero */
body {
  font-family: 'LatoInicial', sans-serif;
}

/* Mejorar cuando fuente completa está lista */
.fonts-loaded body {
  font-family: 'Lato', sans-serif;
}

Midiendo Rendimiento de Fuentes

Métricas Clave a Rastrear

Antes de Optimización:
├── Total archivos de fuentes: 450 KB
├── Solicitudes de fuentes: 8
├── Tiempo a primer texto: 2.8s (FOIT)
├── CLS por intercambio de fuentes: 0.12
└── Lighthouse Performance: 65

Después de Optimización:
├── Total archivos de fuentes: 85 KB (↓81%)
├── Solicitudes de fuentes: 2 (↓75%)
├── Tiempo a primer texto: 0.3s (↓89%)
├── CLS por intercambio de fuentes: 0.01 (↓92%)
└── Lighthouse Performance: 94

Auditorías de Lighthouse a Revisar

  • “Ensure text remains visible during webfont load”
  • “Preload key requests”
  • “Avoid enormous network payloads”
  • “Minimize main-thread work” (parsing de fuentes)

Lista de Verificación de Optimización

Antes de desplegar, verifica:

  • [ ] Usando formato WOFF2 con respaldo WOFF
  • [ ] font-display: swap en todas las reglas @font-face
  • [ ] Fuentes críticas precargadas en <head>
  • [ ] Fuentes auto-hospedadas (no CDN de terceros)
  • [ ] Subconjuntos creados para necesidades de idioma
  • [ ] Limitado a 2-4 archivos de fuentes total
  • [ ] Métricas de fuente de respaldo coincidentes
  • [ ] Fuente variable usada si se necesitan múltiples pesos
  • [ ] Archivos de fuentes comprimidos y cacheados correctamente

Artículos Relacionados

Aprende más sobre optimizar la carga de fuentes:

📚 Volver al Hub de Performance SEO - Explora todos los temas de rendimiento


Referencias

  1. MDN Web Docs - font-display
  2. web.dev - Best Practices for Fonts
  3. Chrome Developers - Ensure Text Remains Visible
  4. MDN Web Docs - @font-face
  5. CSS-Tricks - A Comprehensive Guide to Font Loading Strategies

Pruébalo Tú Mismo

¿Quieres revisar la carga de fuentes de tu sitio?

🔧 Descarga UXR SEO Analyzer (Gratis, análisis 100% local)


Disclaimer: Los analizadores en esta extensión son guías de referencia basadas en documentación oficial de MDN, web.dev y Chrome Developers. No representan verdades absolutas sobre cómo los motores de búsqueda evalúan tu contenido—solo los motores de búsqueda conocen sus algoritmos internos. Usa estas recomendaciones como punto de partida para mejorar tu sitio.

Última actualización: 15 de diciembre de 2025

Artículos relacionados

Hub de categoría

Hub

Hub de SEO de Rendimiento

El rendimiento es un factor de ranking crítico e impacta directamente la experiencia del usuario

En la misma categoría

Guía detallada

Guía Completa de Optimización de LCP

Largest Contentful Paint (LCP) mide cuándo el elemento de contenido más grande se vuelve visible para los usuarios

Introducción

CLS (Cumulative Layout Shift)

Cumulative Layout Shift (CLS) es uno de los Core Web Vitals de Google—un conjunto de métricas que miden la experiencia real del usuario en tu sitio web

Introducción

Recursos que Bloquean el Renderizado

Los recursos que bloquean el renderizado son archivos que impiden que el navegador muestre contenido a los usuarios hasta que se descarguen y procesen...

Última actualización: