Largest Contentful Paint (LCP)

Navegadores compatibles

  • 77
  • 79
  • 122
  • x

Origen

Históricamente, ha sido un desafío para los desarrolladores web medir la rapidez con la que el contenido principal de una página web se carga y es visible para los usuarios. Las métricas más antiguas, como load o DOMContentLoaded, no funcionan bien porque no se corresponden necesariamente con lo que el usuario ve en la pantalla. Además, las métricas de rendimiento más recientes y centradas en el usuario, como First Contentful Paint (FCP), solo capturan el inicio de la experiencia de carga. Si una página muestra una pantalla de presentación o un indicador de carga, este momento no es muy relevante para el usuario.

En el pasado, recomendábamos métricas de rendimiento, como First Meaningful Paint (FMP) y Speed Index (SI) (ambas disponibles en Lighthouse) para capturar una mayor parte de la experiencia de carga después del procesamiento inicial, pero estas métricas son complejas, difíciles de explicar y a menudo incorrectas, lo que significa que aún no identifican cuándo se carga el contenido principal de la página.

A partir de los debates que se realizaron en el Grupo de trabajo de rendimiento web de W3C y las investigaciones realizadas en Google, descubrimos que una forma más precisa de medir cuándo se carga el contenido principal de una página es observar cuándo se renderiza el elemento más grande.

¿Qué es el LCP?

LCP informa el tiempo de renderización de la imagen o el bloque de texto más grande visible en el viewport, en relación con el momento en que el usuario navegó a la página por primera vez.

¿Qué es una buena puntuación de LCP?

Para proporcionar una buena experiencia del usuario, los sitios deben esforzarse por tener Largest Contentful Paint de 2.5 segundos o menos. Para asegurarte de alcanzar este objetivo para la mayoría de los usuarios, un buen umbral para medir es el percentil 75 de las cargas de páginas, segmentadas entre dispositivos móviles y computadoras de escritorio.

Los valores de LCP correctos son de 2.5 segundos o menos, los valores malos son mayores a 4.0 segundos y cualquier otro valor debe mejorarse
Un buen valor de LCP es de 2.5 segundos o menos.

¿Qué elementos se consideran?

Como se especifica actualmente en la API de Largest Contentful Paint, los tipos de elementos que se consideran para Largest Contentful Paint son los siguientes:

Ten en cuenta que la restricción de los elementos a este conjunto limitado fue intencional para mantener las cosas simples al principio. Es posible que se agreguen elementos adicionales (como la compatibilidad total con <svg>) en el futuro a medida que se realicen más investigaciones.

Además de considerar solo algunos elementos, las mediciones de LCP usan heurísticas para excluir ciertos elementos que los usuarios pueden considerar "sin contenido". En el caso de los navegadores con Chromium, estos son algunos de ellos:

  • Elementos con una opacidad de 0, que son invisibles para el usuario
  • Elementos que cubren todo el viewport, que probablemente se consideren como fondo y no como contenido
  • Imágenes de marcadores de posición y otras con baja entropía, que probablemente no reflejen el verdadero contenido de la página

Es probable que los navegadores sigan mejorando esta heurística para garantizar que cumplan con las expectativas de los usuarios en cuanto a cuál es el elemento contentful más grande.

Estas heurísticas con "contenido" pueden diferir de las que usa el primer procesamiento de imagen con contenido (FCP), que puede considerar algunos de estos elementos, como imágenes de marcador de posición o imágenes de viewport completo, incluso si no son aptas para ser candidatos de LCP. A pesar de que ambas usan “contentful” en el nombre, el objetivo de estas métricas es diferente. El FCP mide cuando cualquier contenido se pinta en la pantalla y el LCP cuando se pinta el contenido principal, de modo que el LCP sea más selectivo.

¿Cómo se determina el tamaño de un elemento?

El tamaño del elemento informado para LCP suele ser el tamaño visible para el usuario dentro del viewport. Si el elemento se extiende fuera del viewport, o si alguno de ellos se recorta o tiene un overflow no visible, esas partes no se consideran en el tamaño del elemento.

En el caso de los elementos de imagen a los que se les cambió el tamaño desde su tamaño intrínseco, el tamaño que se informa es el visible o el intrínseco, el que sea menor.

Para los elementos de texto, LCP considera solo el rectángulo más pequeño que puede contener todos los nodos de texto.

Para todos los elementos, el LCP no tiene en cuenta los márgenes, los paddings ni los bordes aplicados con CSS.

¿Cuándo se informa el LCP?

A menudo, las páginas web se cargan en etapas y, por consiguiente, es posible que cambie el elemento más grande de la página.

Para controlar este potencial de cambio, el navegador envía un PerformanceEntry de tipo largest-contentful-paint que identifica el elemento más grande con contenido tan pronto como el navegador pinta el primer fotograma. Sin embargo, después de renderizar los fotogramas posteriores, enviará otro PerformanceEntry cada vez que cambie el elemento con contenido más importante.

Por ejemplo, en una página con texto y una imagen hero, el navegador inicialmente podría solo renderizar el texto. En ese momento, el navegador despacha una entrada largest-contentful-paint cuya propiedad element probablemente haría referencia a <p> o <h1>. Más adelante, una vez que la imagen hero termine de cargarse, se enviará una segunda entrada largest-contentful-paint y su propiedad element hará referencia a <img>.

Un elemento solo se puede considerar el elemento con contenido más grande después de que se renderiza y es visible para el usuario. Las imágenes que aún no se cargaron no se consideran "renderizadas". Tampoco los nodos de texto que usan fuentes web durante el período de bloqueo de fuentes. En esos casos, un elemento más pequeño podría informarse como el elemento con contenido más grande, pero apenas se termina de renderizar el elemento más grande, se crea otro PerformanceEntry.

Además de las imágenes y fuentes de carga tardía, una página puede agregar nuevos elementos al DOM a medida que hay nuevo contenido disponible. Si alguno de estos elementos nuevos es más grande que el elemento con contenido más grande anterior, también se informará un PerformanceEntry nuevo.

Si se quita el elemento con contenido más grande del viewport, o incluso del DOM, se mantiene como el elemento con contenido de mayor tamaño, a menos que se renderice un elemento más grande.

El navegador dejará de informar entradas nuevas tan pronto como el usuario interactúe con la página (cuando se presiona, se desplaza o presiona una tecla), ya que la interacción del usuario con frecuencia cambia lo que es visible para el usuario (lo que ocurre especialmente cuando se desplaza por la pantalla).

Para fines de análisis, solo debes informar el último PerformanceEntry enviado a tu servicio de estadísticas.

Tiempo de carga en comparación con tiempo de renderización

Por motivos de seguridad, la marca de tiempo de renderización de las imágenes no se expone en las imágenes de origen cruzado que no tienen el encabezado Timing-Allow-Origin. En cambio, solo se expone su tiempo de carga (dado que ya está expuesto a través de muchas otras APIs web).

Esto puede llevar a la situación aparentemente imposible en la que las APIs web informan el LCP como antes que FCP. Este no es el caso, pero solo aparece debido a esta restricción de seguridad.

Siempre se recomienda establecer el encabezado Timing-Allow-Origin para que tus métricas sean más precisas.

¿Cómo se manejan los cambios de diseño y tamaño de los elementos?

Para mantener baja la sobrecarga de rendimiento que implica calcular y despachar entradas de rendimiento nuevas, los cambios en el tamaño o la posición de un elemento no generan candidatos de LCP nuevos. Solo se consideran el tamaño inicial y la posición del elemento en el viewport.

Esto significa que es posible que no se informen las imágenes que inicialmente se renderizan fuera de la pantalla y, luego, hacen la transición en ella. También significa que los elementos renderizados inicialmente en el viewport que luego se despliegan hacia abajo y fuera de la vista informarán su tamaño inicial en el viewport.

Ejemplos

Estos son algunos ejemplos de cuándo se produce Largest Contentful Paint en algunos sitios web populares:

Mayor cronograma de procesamiento de imagen con contenido de cnn.com
Un cronograma de LCP de cnn.com
Cronograma de Contentful Paint más grande de techcrunch.com
Un cronograma de LCP de techcrunch.com.

En los dos cronogramas anteriores, los elementos más importantes cambian a medida que se carga el contenido. En el primer ejemplo, se agrega contenido nuevo al DOM y eso cambia el elemento de mayor tamaño. En el segundo ejemplo, los cambios de diseño y el contenido que antes era el más grande se quita del viewport.

Si bien suele ser el caso de que el contenido que se carga tarde es más grande que el que ya se encuentra en la página, no es necesariamente el caso. En los siguientes dos ejemplos, se muestra el LCP que ocurre antes de que la página se cargue por completo.

Cronograma de Contentful Paint más grande de instagram.com
Un cronograma de LCP de instagram.com.
Cronograma de Contentful Paint más grande de google.com
Un cronograma de LCP de google.com.

En el primer ejemplo, el logotipo de Instagram se carga relativamente antes y sigue siendo el elemento más grande incluso cuando se muestra otro contenido de manera progresiva. En el ejemplo de la página de resultados de la Búsqueda de Google, el elemento más grande es un párrafo de texto que se muestra antes de que las imágenes o el logotipo terminen de cargarse. Como todas las imágenes individuales son más pequeñas que este párrafo, sigue siendo el elemento más grande durante todo el proceso de carga.

Cómo medir el LCP

El LCP se puede medir en el lab o en el campo, y está disponible en las siguientes herramientas:

Herramientas de campo

Herramientas del lab

Mide el LCP en JavaScript

Para medir el LCP en JavaScript, puedes usar la API de Largest Contentful Paint. En el siguiente ejemplo, se muestra cómo crear un PerformanceObserver que escuche entradas de largest-contentful-paint y las registre en la consola.

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('LCP candidate:', entry.startTime, entry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});

En el ejemplo anterior, cada entrada de largest-contentful-paint registrada representa el candidato actual para LCP. En general, el valor startTime de la última entrada emitida es el valor de LCP, pero no siempre es así. No todas las entradas largest-contentful-paint son válidas para medir el LCP.

En la siguiente sección, se enumeran las diferencias entre lo que informa la API y cómo se calcula la métrica.

Diferencias entre la métrica y la API

  • La API enviará entradas largest-contentful-paint para las páginas cargadas en una pestaña en segundo plano, pero esas páginas deben ignorarse cuando se calcula el LCP.
  • La API continuará despachando entradas de largest-contentful-paint una vez que la página haya pasado a segundo plano, pero esas entradas se deben ignorar cuando se calcule el LCP (los elementos solo se pueden considerar si la página estuvo en primer plano todo el tiempo).
  • La API no informa entradas largest-contentful-paint cuando se restablece la página desde la memoria caché atrás/adelante, pero el LCP se debe medir en estos casos, ya que los usuarios las experimentan como visitas distintas a la página.
  • La API no tiene en cuenta los elementos dentro de iframes, pero la métrica lo hace porque forman parte de la experiencia del usuario de la página. En las páginas con un LCP dentro de un iframe (por ejemplo, una imagen de póster en un video incorporado), esto se mostrará como una diferencia entre CrUX y RUM. Para medir el LCP correctamente, debes tenerlos en cuenta. Los submarcos pueden usar la API para informar sus entradas largest-contentful-paint al marco superior para la agregación.
  • La API mide el LCP desde el inicio de la navegación, pero para las páginas renderizadas previamente el LCP debe medirse desde activationStart, ya que corresponde al tiempo de LCP tal como lo experimentó el usuario.

En lugar de memorizar todas estas diferencias sutiles, los desarrolladores pueden usar la biblioteca de JavaScript web-vitals para medir el LCP, que se encarga de estas diferencias por ti (cuando sea posible, ten en cuenta que no se trata el problema de iframe):

import {onLCP} from 'web-vitals';

// Measure and log LCP as soon as it's available.
onLCP(console.log);

Consulta el código fuente de onLCP() para obtener un ejemplo completo de la medición del LCP en JavaScript.

¿Qué pasa si el elemento más grande no es el más importante?

En algunos casos, el elemento (o elementos) más importante de la página no es el mismo que el más grande, y es posible que los desarrolladores estén más interesados en medir los tiempos de renderización de estos otros elementos. Esto es posible con la API de Element Timing, como se describe en el artículo sobre métricas personalizadas.

Cómo mejorar el LCP

Hay una guía completa sobre la optimización del LCP que te servirá de guía en el proceso de identificar los tiempos de LCP en el campo y usar los datos de lab para desglosarlos y optimizarlos.

Recursos adicionales

Registro de cambios

Ocasionalmente, se descubren errores en las APIs que se usan para medir métricas y, a veces, en las definiciones de las métricas en sí. Como resultado, a veces es necesario realizar cambios, que pueden aparecer como mejoras o regresiones en tus informes y paneles internos.

Para ayudarte a administrar esto, todos los cambios en la implementación o definición de estas métricas aparecerán en este Registro de cambios.

Si tienes comentarios sobre estas métricas, puedes enviarlos en el grupo de Google web-vitals-feedback.