Históricamente, ha sido un desafío para los desarrolladores web medir la rapidez con la que se carga el contenido principal de una página web 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 su pantalla. Además, las métricas de rendimiento más recientes centradas en el usuario, como el primer procesamiento de imagen con contenido (FCP), solo capturan el comienzo 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, recomendamos métricas de rendimiento como el primer procesamiento de imagen significativo (FMP) y el índice de velocidad (SI) (ambos disponibles en Lighthouse) para ayudar a capturar más de la experiencia de carga después del procesamiento de imagen 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 cargó el contenido principal de la página.
En función de las discusiones en el grupo de trabajo de rendimiento web del W3C y de la investigación realizada 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?
El LCP informa el tiempo de renderización de la imagen, el bloque de texto o el video más grandes visibles en el viewport, en relación con la primera vez que el usuario navegó a la página.
¿Qué es un buen nivel de LCP?
Para proporcionar una buena experiencia del usuario, los sitios deben esforzarse por tener una 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 los dispositivos móviles y las computadoras de escritorio.
¿Qué elementos se tienen en cuenta?
Como se especifica actualmente en la API de Largest Contentful Paint, se consideran los tipos de elementos que se consideran para Largest Contentful Paint:
- Elementos
<img>
(el tiempo de presentación del primer fotograma se usa para contenido animado, como GIFs o PNG animados) - Elementos
<image>
dentro de un elemento<svg>
- Elementos
<video>
(se usa el tiempo de carga de la imagen de póster o el tiempo de presentación del primer fotograma para los videos, lo que ocurra primero) - Un elemento con una imagen de fondo cargada con la función
url()
(en lugar de un gradiente de CSS) - Elementos de nivel de bloque que contienen nodos de texto o algún otro elemento secundario de texto de nivel intercalado.
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 el respaldo completo de <svg>
) 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 es probable que los usuarios consideren "sin contenido". En el caso de los navegadores basados en Chromium, estos incluyen lo siguiente:
- Elementos con una opacidad de 0 que son invisibles para el usuario
- Elementos que cubren todo el viewport y que probablemente se consideren como fondo en lugar de contenido
- Imágenes de marcador de posición u otras imágenes con baja entropía, que probablemente no reflejan el verdadero contenido de la página
Es probable que los navegadores sigan mejorando estas heurísticas para garantizar que coincidamos con las expectativas de los usuarios sobre cuál es el elemento con más contenido.
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 las imágenes de marcadores de posición o las imágenes de viewport completas, incluso si no son aptos para ser candidatos de LCP. A pesar de que ambas incluyen el término "contenido" en su nombre, el objetivo de estas métricas es diferente. El FCP mide cuándo se pinta cualquier contenido en la pantalla y el LCP cuando se pinta el contenido principal, por lo que el LCP se diseñó para ser más selectivo.
¿Cómo se determina el tamaño de un elemento?
Por lo general, el tamaño del elemento informado para la LCP es el que el usuario puede ver dentro del viewport. Si el elemento se extiende fuera del viewport, o si alguno de ellos está recortado o tiene un desbordamiento no visible, esas partes no cuentan para 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, lo que sea más pequeño.
En el caso de los elementos de texto, la LCP solo considera el rectángulo más pequeño que puede contener todos los nodos de texto.
Para todos los elementos, el LCP no considera los márgenes, los rellenos ni los bordes aplicados con CSS.
¿Cuándo se informa el LCP?
Las páginas web suelen cargarse en etapas y, como resultado, 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 de contenido más grande en cuanto el navegador pinta el primer fotograma. Sin embargo, después de renderizar los fotogramas posteriores, enviará otro PerformanceEntry
cada vez que cambie el elemento de contenido más grande.
Por ejemplo, en una página con texto y una imagen hero, es posible que el navegador solo renderice el texto al principio, en cuyo caso enviaría una entrada largest-contentful-paint
cuya propiedad element
probablemente haga referencia a un <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 más contenido 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 lo hacen los nodos de texto que usan fuentes web durante el período de bloqueo de fuentes. En esos casos, es posible que un elemento más pequeño se informe como el elemento con contenido más grande, pero en cuanto se termina de renderizar el elemento más grande, se crea otro PerformanceEntry
.
Además de las imágenes y las fuentes que se cargan tarde, una página puede agregar elementos nuevos al DOM a medida que el contenido nuevo esté 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 nuevo PerformanceEntry
.
Si se quita el elemento con contenido más grande del viewport o incluso del DOM, seguirá siendo el elemento con contenido más grande, a menos que se renderice un elemento más grande.
El navegador dejará de informar entradas nuevas en cuanto el usuario interactúe con la página (a través de una presión, un desplazamiento o una pulsación de tecla), ya que la interacción del usuario suele cambiar lo que el usuario ve (lo que es especialmente cierto con el desplazamiento).
Para fines de análisis, solo debes informar el PerformanceEntry
enviado más recientemente a tu servicio de estadísticas.
Tiempo de carga en comparación con el tiempo de renderización
Por motivos de seguridad, la marca de tiempo de renderización de las imágenes no se expone para las imágenes de origen cruzado que no tienen el encabezado Timing-Allow-Origin
. En cambio, solo se expone su tiempo de carga (ya que este ya se expone a través de muchas otras APIs web).
Esto puede generar una situación aparentemente imposible en la que las APIs web informan que el LCP es anterior al FCP. No es el caso, pero solo aparece así debido a esta restricción de seguridad.
Siempre que sea posible, se recomienda configurar 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 del cálculo y envío de nuevas entradas de rendimiento, los cambios en el tamaño o la posición de un elemento no generan candidatos de LCP nuevos. Solo se considera el tamaño y la posición iniciales 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, pasan a la pantalla. También significa que los elementos renderizados inicialmente en el viewport que luego se desplazan hacia abajo y quedan fuera de la vista seguirán informando su tamaño inicial en el viewport.
Ejemplos
Estos son algunos ejemplos de cuándo se produce el Procesamiento de imagen con contenido más grande en algunos sitios web populares:
En ambos cronogramas anteriores, el elemento más grande cambia a medida que se carga el contenido. En el primer ejemplo, se agrega contenido nuevo al DOM, lo que cambia el elemento más grande. En el segundo ejemplo, el diseño cambia y el contenido que antes era el más grande se quita del viewport.
Si bien, a menudo, el contenido que se carga más tarde es más grande que el que ya está en la página, no siempre es así. En los siguientes dos ejemplos, se muestra que el LCP ocurre antes de que la página se cargue por completo.
En el primer ejemplo, el logotipo de Instagram se carga con bastante anticipación y sigue siendo el elemento más grande, incluso mientras se muestra progresivamente otro contenido. 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 se termine de cargar cualquiera de las imágenes o el logotipo. Debido a que 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
- Informe de experiencia del usuario de Chrome
- PageSpeed Insights
- Search Console (informe de Core Web Vitals)
- Biblioteca de JavaScript de
web-vitals
Herramientas de 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 las 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 registrada de largest-contentful-paint
representa el candidato de LCP actual. En general, el valor de startTime
de la última entrada emitida es el valor de LCP; sin embargo, no siempre es así. No todas las entradas de 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 se deben ignorar cuando se calcula el LCP. - La API seguirá enviando entradas
largest-contentful-paint
después de que una página se haya enviado a segundo plano, pero esas entradas se deben ignorar cuando se calcula el LCP (los elementos solo se pueden considerar si la página estuvo en primer plano todo el tiempo). - La API no informa entradas de
largest-contentful-paint
cuando la página se restablece desde la caché de atrás/adelante, pero se debe medir la LCP en estos casos, ya que los usuarios las experimentan como visitas a páginas distintas. - La API no considera los elementos dentro de los iframes, pero la métrica sí, ya que forman parte de la experiencia del usuario en 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 aparecerá como una diferencia entre CrUX y RUM. Para medir correctamente el LCP, debes considerarlos. Los submarcos pueden usar la API a fin de informar sus entradas de
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 se debe medir desde
activationStart
, ya que corresponde al tiempo de LCP que experimenta el usuario.
En lugar de memorizar todas estas diferencias sutiles, los desarrolladores pueden usar la biblioteca de JavaScript web-vitals
para medir la LCP, que controla estas diferencias por ti (siempre que sea posible, ten en cuenta que no se aborda el problema del 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 cómo medir el LCP en JavaScript.
¿Qué sucede si el elemento más grande no es el más importante?
En algunos casos, el elemento (o los elementos) más importantes de la página no es el mismo que el más grande, y los desarrolladores pueden estar más interesados en medir los tiempos de renderización de esos 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 disponible una guía completa sobre la optimización del LCP para guiarte en el proceso de identificación de los tiempos de LCP en el campo y usar los datos de lab para desglosarlos y optimizarlos.
Recursos adicionales
- Lecciones aprendidas de la supervisión del rendimiento en Chrome, por Annie Sullivan en performance.now() (2019)
Registro de cambios
En ocasiones, se descubren errores en las APIs que se usan para medir las métricas y, a veces, en las definiciones de las métricas. Como resultado, es necesario realizar cambios a veces, y estos 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 se mostrarán en este registro de cambios.
Si tienes comentarios sobre estas métricas, puedes enviarlos al grupo de Google web-vitals-feedback.