Saltar al contenido
12 de mayo de 2026 · 7 min de lectura

Core Web Vitals en Next.js: lo que de verdad mueve la aguja

LCP, CLS e INP explicados con las decisiones concretas que aplicamos en producción: fuentes, imágenes, animaciones y presupuesto de JavaScript.

Las Core Web Vitals se explican mal casi siempre. Se habla de puntuaciones y no de decisiones. Esto es lo que aplicamos en producción, en el orden en que mueve la aguja.

LCP: el elemento grande, no el sitio entero

El Largest Contentful Paint mide cuándo aparece el elemento más grande visible al cargar. En una web de agencia suele ser el titular o la imagen del hero. Tres decisiones se llevan casi todo el resultado:

  • Fuentes con next/font. Se autoalojan en el build, se precargan y se les asigna display: swap. Se acabaron las peticiones a un dominio externo antes de poder pintar texto.
  • Una sola imagen con priority. La del hero y ninguna más. Todo lo demás va con loading="lazy". Poner priority en media docena de imágenes es la forma más rápida de empeorar el LCP.
  • Vídeo de fondo que no compite. El póster se sirve como imagen normal y el vídeo se monta después del primer pintado. El LCP lo marca el póster o el titular, nunca la descarga del .mp4.

Si el LCP sigue alto después de esto, el problema casi siempre está en el servidor: tiempo de respuesta, no de pintado.

CLS: reservar el hueco antes de tenerlo

El Cumulative Layout Shift mide cuánto se mueve el contenido después de aparecer. Las causas son siempre las mismas:

  1. Imágenes sin dimensiones. Con next/image y fill dentro de un contenedor con aspect-ratio el hueco está reservado desde el primer frame.
  2. Fuentes que cambian de métrica al cargar. next/font genera un fallback ajustado y el salto desaparece.
  3. Banners y avisos que se insertan arriba del todo. Si hay que mostrarlos, van en position: fixed, fuera del flujo.

INP: el coste de responder

El Interaction to Next Paint sustituyó al FID y es mucho más exigente: mide el retraso entre la interacción y el siguiente pintado, incluyendo el trabajo del hilo principal. Lo que nos funciona:

  • Animar solo transform y opacity. Son propiedades de compositor: no provocan layout ni paint. Animar width, height, top o left obliga al navegador a recalcular en cada frame y se come el presupuesto justo cuando el usuario hace clic.
  • Librerías de animación con import() dinámico. GSAP y ScrollTrigger pesan más que el resto del bundle de una landing. Si solo se usan en dos secciones, se cargan en esas dos secciones y después del primer pintado.
  • Nada de escuchar scroll sin requestAnimationFrame. Un listener que lee getBoundingClientRect() en cada evento fuerza reflow decenas de veces por segundo.

El presupuesto de rendimiento

Una regla simple evita discusiones: cada dependencia nueva tiene que justificar su peso. Antes de instalar, se mira cuánto añade al bundle del cliente y qué componente la necesita. Si solo la usa una sección, se carga solo ahí.

En nuestros proyectos el presupuesto es explícito: JavaScript de primera carga por debajo de 120 KB comprimido, LCP por debajo de 2 segundos en 4G simulada y CLS por debajo de 0,05. Si un cambio lo rompe, no se despliega.

Qué medir después de desplegar

Lighthouse en local es una simulación. Los datos que cuentan son los de campo, los que Google recoge de usuarios reales (CrUX). Un sitio puede sacar 100 en Lighthouse y tener malas métricas reales si el servidor va lento en hora punta o si el 60 % del tráfico entra desde móviles antiguos.

Por eso conectamos analítica de Web Vitals desde el primer día: los percentiles 75 de LCP, CLS e INP se revisan cada semana durante el primer mes. Ahí es donde aparecen los problemas que ninguna auditoría en local enseña.

Contacto

Cuéntanos qué quieres construir

Respondemos en menos de 24 horas laborables con una primera valoración: si encaja, qué haría falta y un rango de precio. Sin llamadas de descubrimiento de una hora.

  • Respuesta en menos de 24 h laborables
  • Presupuesto cerrado, sin tarifa por horas
  • Te contesta quien va a escribir el código

Al enviar aceptas nuestra política de privacidad. No compartimos tus datos con nadie.