⚡ Performance, SEO & Accesibilidad

Core Web Vitals en 2026: INP, LCP, CLS y cómo optimizarlos de verdad

INP, LCP y CLS explicados métrica a métrica: qué miden exactamente, cómo se calculan sobre datos reales de usuario y qué cambios de código las mueven de verdad.

📅 14 de enero de 2026 ⏱️ 10 min de lectura ✍️ Equipo ProgramacionWebs

Cada cierto tiempo alguien pregunta si Core Web Vitals sigue importando en 2026. La respuesta corta es sí, pero la pregunta interesante ya no es “¿importa?” sino “¿qué parte controlo yo de verdad como developer?”. Las tres métricas —LCP, INP y CLS— llevan sin cambiar sus umbrales desde 2024, y eso es una buena noticia: da tiempo a entender qué mueven realmente en el motor del navegador en lugar de perseguir un número que cambia cada trimestre.

Este artículo va de eso: qué mide cada métrica a nivel técnico, por qué INP reemplazó a First Input Delay (FID) y qué cambios de código —no trucos genéricos— las mueven en la práctica.

Qué son exactamente los Core Web Vitals

Core Web Vitals es un subconjunto de las métricas de Web Vitals que Google considera suficientemente importante como para influir en cómo evalúa la experiencia de una página. Se miden en el percentil 75 de las visitas reales de los últimos 28 días, segmentado por dispositivo (móvil y escritorio se evalúan por separado). Eso significa que optimizar para “que salga bien en mi portátil con fibra” no dice nada: lo que cuenta es cómo lo vive el 75% de tus visitas reales, incluida la gente con un móvil de gama media y una red 4G saturada.

Las tres métricas actuales son:

  • LCP (Largest Contentful Paint): tiempo hasta que se pinta el elemento más grande visible en el viewport inicial. Umbral bueno: ≤ 2.5 segundos.
  • INP (Interaction to Next Paint): latencia de la interacción más lenta (o cercana a la más lenta) de toda la visita. Umbral bueno: ≤ 200 milisegundos.
  • CLS (Cumulative Layout Shift): suma de todos los desplazamientos de layout inesperados durante la vida de la página. Umbral bueno: ≤ 0.1.

Un detalle que se pasa por alto: estas métricas se calculan con datos de campo (Chrome UX Report, CrUX), no con la ejecución de Lighthouse en tu máquina. Lighthouse te da una simulación de laboratorio, útil para depurar, pero lo que afecta a Search es lo que reporta CrUX desde navegadores Chrome reales. Puedes tener un Lighthouse en verde y un CrUX en rojo si tu tráfico real usa gama baja o redes lentas que tu laboratorio no reproduce.

Por qué INP sustituyó a FID

Hasta marzo de 2024, la métrica de responsividad era First Input Delay (FID): medía solo el tiempo entre que el usuario hace la primera interacción y el navegador empieza a procesar el evento correspondiente. Tenía dos problemas serios:

  1. Solo miraba la primera interacción. Una página podía tener un FID excelente y luego volverse completamente inmanejable a partir del segundo clic, y FID nunca lo reflejaba.
  2. Medía delay de entrada, no la interacción completa. FID terminaba de contar en cuanto empezaba a ejecutarse el event handler; no incluía ni el tiempo de procesamiento del propio handler ni el tiempo hasta que el navegador pintaba el siguiente frame visualmente.

INP corrige ambos problemas: observa todas las interacciones (clics, taps, pulsaciones de teclado) durante toda la sesión y reporta la más lenta (o, en páginas con muchas interacciones, un percentil alto de todas ellas), midiendo desde el input hasta el frame en que el navegador pinta la respuesta visual. Es una medida mucho más honesta de “¿esta interfaz se siente rota cuando la uso de verdad?”.

La consecuencia práctica es que INP castiga patrones que FID ignoraba por completo: listas infinitas que se degradan tras cargar más elementos, SPAs que acumulan listeners sin limpiarlos, formularios que recalculan validaciones pesadas en cada tecla. Es, con diferencia, la métrica que más sitios siguen fallando en 2026 —una proporción significativa de webs con tráfico real sigue por encima de los 200 ms en el percentil 75—, precisamente porque exige repensar la arquitectura de JavaScript, no solo comprimir imágenes.

graph LR
A[Usuario interactúa] --> B[Input delay: cola de tareas]
B --> C[Processing time: ejecución del handler]
C --> D[Presentation delay: hasta pintar el frame]
D --> E[INP = A hasta D]

LCP: qué lo mueve de verdad

LCP no es “lo rápido que carga la página”: es el tiempo hasta que se pinta el elemento de contenido más grande del viewport inicial (normalmente una imagen hero, un bloque de texto grande o un vídeo con poster). Se descompone en cuatro fases, y cada una tiene su propia palanca:

  1. Time to First Byte (TTFB): cuánto tarda el servidor en responder la petición del documento HTML. Si tu TTFB ya consume 1.5 s de los 2.5 s de presupuesto, no hay optimización de frontend que lo arregle. Aquí entran: SSR eficiente, edge rendering, caché de CDN y evitar redirecciones innecesarias en la cadena de carga.
  2. Retraso de carga del recurso: tiempo hasta que el navegador empieza a descargar el recurso LCP (normalmente una imagen). Si esa imagen se descubre tarde —por ejemplo, porque la inyecta un <script> en vez de estar en el HTML inicial, o porque no tiene fetchpriority="high"—, pierdes tiempo aunque el archivo en sí sea pequeño.
  3. Tiempo de carga del recurso: tamaño del archivo entre ancho de banda disponible. Aquí es donde entran formato de imagen, compresión y srcset — lo desarrollamos en detalle en el artículo sobre optimización de imágenes en la web moderna.
  4. Retraso de renderizado: tiempo entre que el recurso está disponible y el navegador realmente lo pinta, normalmente bloqueado por JavaScript o CSS que se ejecuta antes en el hilo principal.

Las técnicas con más impacto real, en orden de prioridad:

<!-- Preload de la imagen LCP, con prioridad alta -->
<link rel="preload" as="image" href="/hero.avif" fetchpriority="high" />
<img src="/hero.avif" alt="..." fetchpriority="high" />
  • Preload + fetchpriority="high" en el recurso LCP: adelanta el descubrimiento del recurso crítico en vez de esperar a que el parser de HTML llegue a esa línea o a que se ejecute JavaScript.
  • CSS crítico inline: el CSS que afecta al contenido visible en el primer viewport no debería depender de una hoja de estilos externa render-blocking. Astro y frameworks similares ya insertan CSS crítico automáticamente en build, pero si añades CSS de terceros de forma manual, revisa que no bloquee el render.
  • font-display: swap (o optional) y preload de fuentes: evita que el texto quede invisible (FOIT) mientras se descarga la tipografía, y evita que la fuente tardía dispare un layout shift al llegar.
  • Server-side rendering o pre-render frente a client-side rendering puro: si el contenido LCP solo aparece después de que React o Vue hidraten y hagan un fetch, ya perdiste la carrera antes de empezar.

INP: cómo se optimiza en la práctica

Aquí no hay un solo fix; es un conjunto de disciplinas sobre el hilo principal.

1. Rompe las tareas largas. Cualquier tarea de JavaScript que ocupe el hilo principal más de 50 ms bloquea la respuesta a la siguiente interacción del usuario. La técnica es “yielding”: trocear el trabajo y devolver el control al navegador entre trozos.

// Antes: una tarea larga que bloquea el hilo principal
function procesarListaCompleta(items: Item[]) {
  for (const item of items) {
    procesarItem(item); // 300ms de trabajo total
  }
}

// Después: se cede el control entre lotes
async function procesarListaPorLotes(items: Item[]) {
  for (let i = 0; i < items.length; i += 50) {
    const lote = items.slice(i, i + 50);
    lote.forEach(procesarItem);
    // yield al hilo principal antes de seguir
    await new Promise((resolve) => setTimeout(resolve, 0));
  }
}

En navegadores compatibles, scheduler.yield() hace lo mismo de forma más precisa que un setTimeout(0).

2. Difiere el trabajo que no es visualmente crítico. Analytics, tracking de terceros, hidratación de componentes fuera del viewport: todo eso puede esperar a requestIdleCallback o cargarse tras el evento de interacción principal. En Astro esto se traduce directamente en elegir bien la directiva de hidratación (client:idle, client:visible) en lugar de client:load por defecto.

3. Minimiza el trabajo dentro del propio event handler. Si un click dispara una validación de formulario completa, un re-render de una tabla de 2.000 filas y una petición de red síncrona antes de pintar nada, cada uno de esos pasos suma a la latencia. Separa “lo que tiene que pasar antes del siguiente frame” (feedback visual inmediato) de “lo que puede pasar después” (la lógica de negocio real).

4. Reduce la complejidad del DOM. Cuantos más nodos tenga que recalcular el navegador en cada actualización (estilos, layout), más caro es cada re-render. Listas virtualizadas en vez de renderizar miles de filas de golpe es la solución habitual.

CLS: por qué sigue rompiéndose en 2026

CLS mide desplazamientos de layout inesperados: cuando un elemento visible se mueve sin que el usuario haya interactuado justo antes. Las causas más frecuentes no han cambiado en años, lo cual dice mucho de lo poco disciplinados que seguimos siendo con esto:

  • Imágenes y vídeos sin width/height (o aspect-ratio): el navegador no puede reservar el espacio hasta que el recurso termina de descargar, así que el contenido de alrededor “salta” cuando llega.
  • Anuncios e iframes de terceros inyectados dinámicamente: reserva el espacio con un contenedor de tamaño fijo o mínimo antes de que cargue el slot.
  • Fuentes web que cambian el ancho del texto al sustituir la fuente de sistema por la fuente descargada (esto se llama FOUT). font-display: optional o el uso de size-adjust en @font-face minimizan el salto.
  • Contenido inyectado por encima de contenido existente sin reservar espacio, típicamente banners de cookies o notificaciones que empujan el layout en vez de superponerse con position: fixed o position: absolute.

La solución técnica es casi siempre la misma: reservar espacio explícitamente antes de que el contenido real esté disponible.

img, video {
  aspect-ratio: attr(width) / attr(height); /* fallback conceptual */
}

En la práctica, basta con no omitir nunca los atributos width y height en el HTML —incluso si el CSS después hace la imagen responsive con width: 100%; height: auto— porque el navegador usa esos atributos para calcular el aspect-ratio intrínseco antes de que el archivo cargue.

Medir antes de optimizar

Optimizar a ciegas es la forma más rápida de perder tiempo en el sitio equivocado. El proceso correcto siempre empieza por diagnóstico con datos reales: revisa el informe de campo en Search Console, cruza con PageSpeed Insights para lab data, y prioriza por impacto y volumen de tráfico afectado antes de tocar código. Ese proceso completo, con ejemplo paso a paso, lo desarrollamos en cómo auditar y mejorar el rendimiento de una web.

Ninguna de las tres métricas se arregla con un solo cambio. LCP depende de la cadena crítica de carga, INP depende de cómo está diseñada tu concurrencia en JavaScript, y CLS depende de disciplina en el marcado. Lo que sí es cierto es que las tres recompensan lo mismo: menos trabajo innecesario en el camino crítico, y más control explícito sobre qué se pinta cuándo.

Compartir