Ver contenido
Guía Completa de Optimización de LCP: Técnicas Avanzadas para Tiempos de Carga Más Rápidos
Introducción
Largest Contentful Paint (LCP) mide cuándo el elemento de contenido más grande se vuelve visible para los usuarios. Aunque lograr una buena puntuación de LCP (menos de 2.5 segundos) puede parecer sencillo, optimizar LCP requiere entender los factores subyacentes y aplicar técnicas específicas.
Esta guía cubre estrategias de optimización avanzadas basadas en las recomendaciones oficiales de Google y datos de rendimiento del mundo real de millones de sitios web.
Entendiendo las Sub-Partes de LCP
Según la documentación de web.dev, LCP puede desglosarse en cuatro fases distintas. Entender estas fases es crucial para una optimización dirigida:
La Línea de Tiempo de LCP
Inicio de Carga → TTFB → Retraso de Carga de Recurso → Tiempo de Carga → Retraso de Renderizado → LCP
Presupuesto óptimo para objetivo de 2.5s:
├── TTFB: ~800ms (40%)
├── Retraso de Carga de Recurso: ~100ms (menos es mejor)
├── Tiempo de Carga de Recurso: ~800ms (40%)
└── Retraso de Renderizado: ~100ms (menos es mejor)
Fase 1: Time to First Byte (TTFB)
El tiempo desde el inicio de la navegación hasta que el navegador recibe el primer byte de HTML. Objetivo: Menos de 800ms.
Fase 2: Retraso de Carga de Recurso
El tiempo entre TTFB y cuando el navegador comienza a cargar el recurso LCP. Objetivo: Minimizar a casi cero.
Fase 3: Tiempo de Carga de Recurso
Cuánto tiempo tarda en cargar el recurso LCP (típicamente una imagen). Objetivo: Menos de 800ms.
Fase 4: Retraso de Renderizado del Elemento
El tiempo desde que el recurso carga hasta que se renderiza en pantalla. Objetivo: Minimizar a casi cero.
Optimizaciones del Lado del Servidor
1. Reducir TTFB
TTFB es la base de un buen LCP. Cada milisegundo ahorrado aquí fluye hacia la mejora de LCP.
Usa una CDN para assets estáticos:
Sin CDN:
Usuario (Chile) → Servidor (US) = 200ms latencia × 3 viajes = 600ms TTFB
Con CDN:
Usuario (Chile) → CDN Edge (Chile) = 20ms latencia × 3 viajes = 60ms TTFB
Habilita caché del lado del servidor:
# Nginx - Cachear assets estáticos
location ~* \.(jpg|jpeg|png|webp|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Cachear HTML para páginas estáticas
location / {
add_header Cache-Control "public, max-age=3600, stale-while-revalidate=86400";
}
Usa HTTP/2 o HTTP/3:
# Configuración HTTP/2 en Nginx
server {
listen 443 ssl http2;
# HTTP/3 (QUIC) si está soportado
listen 443 quic;
add_header Alt-Svc 'h3=":443"; ma=86400';
}
2. Implementa Stale-While-Revalidate
Permite servir contenido cacheado mientras se obtiene contenido fresco en segundo plano:
Cache-Control: public, max-age=60, stale-while-revalidate=3600
Esto significa:
- Servir contenido cacheado por 60 segundos
- Después de 60 segundos, servir contenido obsoleto mientras revalida en segundo plano
- El contenido se considera obsoleto pero usable hasta por 1 hora
Eliminar el Retraso de Carga de Recursos
El objetivo es hacer que el navegador descubra y comience a cargar el recurso LCP lo más temprano posible.
1. Precargar Imágenes LCP
Para imágenes que no son descubribles en el HTML inicial:
<head>
<!-- Precarga con fetchpriority alto -->
<link rel="preload"
as="image"
href="/images/hero.webp"
fetchpriority="high">
<!-- Para imágenes responsivas -->
<link rel="preload"
as="image"
href="/images/hero.webp"
imagesrcset="/images/hero-400.webp 400w,
/images/hero-800.webp 800w,
/images/hero-1200.webp 1200w"
imagesizes="100vw">
</head>
2. Inlinear CSS Crítico
CSS bloquea el renderizado. Inlinea el CSS necesario para contenido above-the-fold:
<head>
<!-- CSS crítico inlineado -->
<style>
/* Solo estilos necesarios para contenido above-the-fold */
.hero {
position: relative;
min-height: 500px;
}
.hero-image {
width: 100%;
height: auto;
}
</style>
<!-- Cargar stylesheet completo asíncronamente -->
<link rel="preload" href="/styles/main.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="/styles/main.css">
</noscript>
</head>
3. Evitar Lazy Loading en Elementos LCP
Según datos de HTTP Archive, el lazy loading de la imagen LCP es uno de los errores más comunes:
<!-- ❌ Error común: lazy loading de imagen hero -->
<img src="hero.webp" loading="lazy" alt="Hero">
<!-- ✅ Correcto: carga eager con prioridad alta -->
<img src="hero.webp"
loading="eager"
fetchpriority="high"
decoding="async"
alt="Hero">
4. Eliminar JavaScript que Bloquea el Renderizado
Mueve scripts no críticos al final o usa async/defer:
<!-- ❌ Bloquea renderizado -->
<script src="analytics.js"></script>
<!-- ✅ No bloquea renderizado -->
<script src="analytics.js" defer></script>
<!-- ✅ Carga en paralelo, ejecuta cuando está listo -->
<script src="analytics.js" async></script>
Cuándo usar cada uno:
defer: Scripts que necesitan DOM listo, ejecutan en ordenasync: Scripts independientes como analytics, ejecutan inmediatamente al cargar
Optimizar el Tiempo de Carga de Recursos
1. Usar Formatos de Imagen Modernos
WebP y AVIF proporcionan reducciones de tamaño significativas:
<picture>
<!-- AVIF: Mejor compresión, soporte limitado -->
<source type="image/avif" srcset="hero.avif">
<!-- WebP: Buena compresión, amplio soporte -->
<source type="image/webp" srcset="hero.webp">
<!-- JPEG: Fallback para navegadores antiguos -->
<img src="hero.jpg" alt="Imagen hero">
</picture>
Ahorros típicos:
JPEG Original: 500KB (base)
WebP: 300KB (-40%)
AVIF: 200KB (-60%)
2. Implementar Imágenes Responsivas
Sirve imágenes del tamaño apropiado para cada viewport:
<img src="hero-800.webp"
srcset="hero-400.webp 400w,
hero-800.webp 800w,
hero-1200.webp 1200w,
hero-1600.webp 1600w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 80vw,
1200px"
alt="Imagen hero"
width="1200"
height="600"
fetchpriority="high">
3. Usar CDN de Imágenes para Optimización Dinámica
Servicios como Cloudflare Images, imgix, o Cloudinary pueden optimizar imágenes al vuelo:
<!-- Redimensionamiento de Imagen Cloudflare -->
<img src="/cdn-cgi/image/width=800,format=auto,quality=80/hero.jpg"
alt="Hero">
<!-- Dimensionamiento dinámico basado en viewport -->
<img src="/cdn-cgi/image/width=auto,format=auto/hero.jpg"
sizes="100vw"
alt="Hero">
4. Optimizar Carga de Fuentes para LCP de Texto
Si tu elemento LCP es texto, la carga de fuentes puede retrasarlo:
<head>
<!-- Precargar fuente crítica -->
<link rel="preload"
href="/fonts/main.woff2"
as="font"
type="font/woff2"
crossorigin>
<!-- Usar font-display: swap -->
<style>
@font-face {
font-family: 'MainFont';
src: url('/fonts/main.woff2') format('woff2');
font-display: swap;
}
</style>
</head>
Minimizar el Retraso de Renderizado del Elemento
1. Evitar CSS que Oculta Elementos LCP
Animaciones CSS o estados iniciales ocultos retrasan LCP:
/* ❌ Retrasa LCP - elemento comienza oculto */
.hero-image {
opacity: 0;
animation: fadeIn 0.5s forwards;
}
/* ✅ Mejor - elemento visible inmediatamente */
.hero-image {
opacity: 1;
}
2. Reducir JavaScript que Modifica el Elemento LCP
El renderizado del lado del cliente que construye el elemento LCP lo retrasa:
// ❌ LCP retrasado hasta que JS ejecuta
document.getElementById('hero').innerHTML = '<img src="hero.webp">';
// ✅ Mejor - incluir elemento LCP en HTML
// Dejar que el navegador lo maneje nativamente
3. Usar Content-Visibility para Contenido Below-Fold
Previene que el contenido below-fold afecte el renderizado de LCP:
/* Saltar renderizado de contenido fuera de pantalla */
.below-fold-section {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}
Técnicas de Optimización Avanzadas
1. Priority Hints
Usa el atributo fetchpriority para señalar la importancia de recursos:
<!-- Alta prioridad para imagen LCP -->
<img src="hero.webp" fetchpriority="high" alt="Hero">
<!-- Baja prioridad para imágenes below-fold -->
<img src="footer-logo.webp" fetchpriority="low" alt="Logo">
<!-- Alta prioridad para script crítico -->
<script src="critical.js" fetchpriority="high"></script>
2. Early Hints (Código de Estado 103)
Envía hints sobre recursos críticos antes de la respuesta principal:
HTTP/1.1 103 Early Hints
Link: </styles/critical.css>; rel=preload; as=style
Link: </images/hero.webp>; rel=preload; as=image
HTTP/1.1 200 OK
Content-Type: text/html
...
3. Carga Especulativa
Pre-renderiza páginas que los usuarios probablemente visitarán:
<!-- API de Speculation Rules -->
<script type="speculationrules">
{
"prerender": [
{
"where": { "href_matches": "/productos/*" },
"eagerness": "moderate"
}
]
}
</script>
Medición y Monitoreo de LCP
Pruebas de Laboratorio
# Lighthouse CLI
lighthouse https://ejemplo.com --only-categories=performance
# WebPageTest
webpagetest test https://ejemplo.com --location=ec2-sa-east-1
Datos de Campo (RUM)
// Librería Web Vitals
import {onLCP} from 'web-vitals';
onLCP(({value, element}) => {
console.log('LCP:', value, 'Elemento:', element);
// Enviar a analytics
analytics.track('LCP', {
value,
element: element?.tagName,
url: window.location.href
});
});
Chrome DevTools
- Abre DevTools → pestaña Performance
- Marca la casilla “Web Vitals”
- Graba una carga de página
- Busca el marcador “LCP” en la línea de tiempo
- Pasa el cursor para ver qué elemento disparó LCP
Patrones Comunes de Optimización de LCP
Patrón 1: Página con Imagen Hero
<!DOCTYPE html>
<html>
<head>
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">
<style>/* CSS crítico inlineado */</style>
</head>
<body>
<img src="hero.webp"
fetchpriority="high"
loading="eager"
width="1200" height="600"
alt="Hero">
</body>
</html>
Patrón 2: Página con Mucho Texto (Blog)
<!DOCTYPE html>
<html>
<head>
<link rel="preload" href="font.woff2" as="font" crossorigin>
<style>
@font-face {
font-family: 'Article';
src: url('font.woff2') format('woff2');
font-display: swap;
}
h1 { font-family: 'Article', serif; }
</style>
</head>
<body>
<h1>Título del Artículo Que Es el Elemento LCP</h1>
</body>
</html>
Lista de Verificación: Optimización de LCP
Servidor y Red
├── [ ] TTFB menor a 800ms
├── [ ] CDN configurado para assets estáticos
├── [ ] HTTP/2 o HTTP/3 habilitado
├── [ ] Compresión (Brotli/Gzip) habilitada
└── [ ] Headers de caché configurados
Descubrimiento de Recursos
├── [ ] Imagen LCP precargada
├── [ ] CSS crítico inlineado
├── [ ] JS que bloquea renderizado eliminado
└── [ ] fetchpriority="high" en elemento LCP
Optimización de Recursos
├── [ ] Formatos de imagen modernos (WebP/AVIF)
├── [ ] Imágenes responsivas con srcset
├── [ ] Dimensiones de imagen especificadas
├── [ ] Fuentes precargadas con font-display: swap
└── [ ] Imagen LCP NO tiene lazy loading
Optimización de Renderizado
├── [ ] Sin CSS ocultando elemento LCP
├── [ ] Sin JS construyendo elemento LCP
├── [ ] content-visibility para below-fold
└── [ ] Scripts de terceros diferidos
Artículos Relacionados
- LCP Explicado - Fundamentos de LCP
- Guía de Optimización de TTFB - Optimización de respuesta del servidor
- Guía de Optimización de FCP - Optimización del primer pintado
- Guía de Optimización de Imágenes - Optimización completa de imágenes
Referencias
Este artículo fue mejorado usando fuentes autoritativas:
[1] web.dev: Optimize Largest Contentful Paint https://web.dev/articles/optimize-lcp Guía completa de Google para optimización de LCP cubriendo las cuatro sub-partes: TTFB, retraso de carga de recurso, tiempo de carga de recurso, y retraso de renderizado del elemento. Incluye técnicas específicas y presupuestos de tiempo para lograr buenas puntuaciones de LCP.
[2] web.dev: LCP Breakdown https://web.dev/articles/lcp#what-is-a-good-lcp-score Desglose detallado de las fases de LCP con asignaciones de tiempo recomendadas. Explica por qué el 40% del presupuesto de 2.5s debería ir a TTFB y tiempo de carga de recurso cada uno, con tiempo mínimo para retrasos.
[3] Chrome Developers: Resource Loading Optimization https://developer.chrome.com/docs/lighthouse/performance/uses-rel-preload Documentación técnica sobre preload hints, atributo fetchpriority, y Priority Hints API para optimizar la carga de recursos críticos que afectan LCP.
[4] HTTP Archive Web Almanac: Performance https://almanac.httparchive.org/en/2024/performance Datos de rendimiento de toda la industria mostrando cuellos de botella comunes de LCP en millones de sitios web, incluyendo tasas de adopción de técnicas de optimización y patrones de mejora del mundo real.
Nota: Este artículo es parte de nuestra serie de análisis SEO. Explora todos los artículos en el Hub de SEO de Rendimiento.
Fuentes: web.dev (Optimización de LCP), Chrome Developers, HTTP Archive Web Almanac