Historicamente, os desenvolvedores Web têm enfrentado desafios para medir a rapidez com que o conteúdo principal de uma página da Web é carregado e fica visível para os usuários. Métricas mais antigas, como load ou DOMContentLoaded, não funcionam bem porque não correspondem necessariamente ao que o usuário vê na tela. E as métricas de performance mais recentes e centradas no usuário, como a First Contentful Paint (FCP), capturam apenas o início da experiência de carregamento. Se uma página mostra uma tela inicial ou um indicador de carregamento, esse momento não é muito relevante para o usuário.
No passado, recomendamos métricas de desempenho como First Meaningful Paint (FMP) e Índice de velocidade (IV) (ambas disponíveis no Lighthouse) para capturar mais da experiência de carregamento após a pintura inicial, mas essas métricas são complexas, difíceis de explicar e, muitas vezes, incorretas, ou seja, elas ainda não identificam quando o conteúdo principal da página foi carregado.
Com base em discussões no Grupo de trabalho de desempenho da Web do W3C e em pesquisas feitas no Google, descobrimos que uma maneira mais precisa de medir quando o conteúdo principal de uma página é carregado é observar quando o maior elemento é renderizado.
O que é LCP?
A LCP informa o tempo de renderização da maior imagem, bloco de texto ou vídeo visível na janela de visualização, em relação ao momento em que o usuário navegou pela primeira vez até a página.
Qual é uma boa pontuação de LCP?
Para oferecer uma boa experiência ao usuário, os sites devem ter uma Largest Contentful Paint de 2,5 segundos ou menos. Para garantir que essa meta seja atingida para a maioria dos usuários, um bom limite é o 75º percentil de carregamentos de página, segmentado em dispositivos móveis e computadores.
Quais elementos são considerados?
Conforme especificado na API Largest Contentful Paint, os tipos de elementos considerados para a Maior exibição de conteúdo são:
- Elementos
<img>
(o tempo de apresentação do primeiro frame é usado para conteúdo animado, como GIFs ou PNGs animados) - Elementos
<image>
dentro de um elemento<svg>
- Elementos
<video>
: o tempo de carregamento da imagem do pôster ou o tempo de apresentação do primeiro frame para vídeos é usado, o que for mais cedo. - Um elemento com uma imagem de plano de fundo carregada usando a função
url()
(e não um gradiente de CSS). - Elementos no nível de bloco que contêm nós de texto ou outros filhos de elementos de texto no nível in-line.
A restrição dos elementos a esse conjunto limitado foi intencional para manter as coisas simples no início. Outros elementos (como o suporte total ao <svg>
) poderão ser adicionados no futuro, conforme mais pesquisas forem realizadas.
Além de considerar apenas alguns elementos, as medições de LCP usam heurística para excluir determinados elementos que os usuários podem considerar "sem conteúdo". Para navegadores baseados no Chromium, isso inclui:
- Elementos com uma opacidade de 0, que são invisíveis para o usuário
- Elementos que cobrem a janela de visualização inteira, que provavelmente são considerados como plano de fundo em vez de conteúdo
- Imagens de marcador de posição ou outras imagens com baixa entropia, que provavelmente não refletem o conteúdo real da página
É provável que os navegadores continuem melhorando essas heurísticas para garantir que atendam às expectativas dos usuários sobre qual é o maior elemento com conteúdo.
Essas heurísticas "com conteúdo" podem ser diferentes daquelas usadas pela First Contentful Paint (FCP), que pode considerar alguns desses elementos, como imagens de marcador de posição ou imagens de janela de visualização completa, mesmo que eles não sejam candidatos à LCP. Apesar de ambos usarem "contentful" no nome, o objetivo dessas métricas é diferente. A FCP mede quando qualquer conteúdo é mostrado na tela e a LCP quando o conteúdo principal é mostrado. Assim, a LCP tem a intenção de ser mais seletiva.
Como é determinado o tamanho de um elemento?
O tamanho do elemento informado para a LCP geralmente é o tamanho visível para o usuário na janela de visualização. Se o elemento se estender para fora da janela de visualização, se algum deles for cortado ou tiver um overflow não visível, essas partes não serão contabilizadas no tamanho do elemento.
Para elementos de imagem que foram redimensionados a partir do tamanho intrínseco, o tamanho informado é o visível ou o intrínseco, o que for menor.
Para elementos de texto, o LCP considera apenas o retângulo menor que pode conter todos os nós de texto.
Para todos os elementos, o LCP não considera margens, paddings ou bordas aplicadas usando CSS.
Quando o LCP é informado?
As páginas da Web geralmente são carregadas em etapas. Por isso, é possível que o elemento maior da página mude.
Para lidar com essa possibilidade de mudança, o navegador envia uma PerformanceEntry
do tipo largest-contentful-paint
, identificando o maior elemento de conteúdo assim que o navegador pinta o primeiro frame. No entanto, depois de renderizar os frames seguintes, ele vai enviar outro PerformanceEntry
sempre que o maior elemento de conteúdo mudar.
Por exemplo, em uma página com texto e uma imagem principal, o navegador pode renderizar apenas o texto. Nesse ponto, ele envia uma entrada largest-contentful-paint
, cuja propriedade element
provavelmente faz referência a um <p>
ou <h1>
. Depois, quando a imagem principal terminar de carregar, uma segunda entrada largest-contentful-paint
será enviada, e a propriedade element
dela vai referenciar o <img>
.
Um elemento só pode ser considerado o maior elemento com conteúdo depois de renderizado e visível para o usuário. As imagens que ainda não foram carregadas não são consideradas "renderizadas". Os nós de texto que usam fontes da Web durante o período de bloqueio de fontes também não são afetados. Nesses casos, um elemento menor pode ser informado como o maior elemento com conteúdo, mas, assim que o elemento maior terminar a renderização, outro PerformanceEntry
será criado.
Além de carregar imagens e fontes com atraso, uma página pode adicionar novos elementos ao DOM conforme novos conteúdos são disponibilizados. Se algum desses novos elementos for maior do que o maior elemento com conteúdo anterior, um novo PerformanceEntry
também será informado.
Se o maior elemento com conteúdo for removido da janela de visualização ou até mesmo do DOM, ele continuará sendo o maior elemento com conteúdo, a menos que um elemento maior seja renderizado.
O navegador vai parar de informar novas entradas assim que o usuário interagir com a página (por meio de um toque, rolagem ou pressionamento de tecla), já que a interação do usuário geralmente muda o que está visível para o usuário (o que é especialmente verdadeiro com a rolagem).
Para fins de análise, informe apenas o PerformanceEntry
enviado mais recentemente ao serviço de análise.
Tempo de carregamento x tempo de renderização
Por motivos de segurança, o carimbo de data/hora de renderização das imagens não é exposto para imagens de origem cruzada que não têm o cabeçalho Timing-Allow-Origin
. Em vez disso, apenas o tempo de carregamento é exposto, já que ele já é exposto por muitas outras APIs da Web.
Isso pode levar a uma situação aparentemente impossível em que o LCP é informado por APIs da Web antes do FCP. Isso não é o caso, mas aparece assim devido a essa restrição de segurança.
Sempre que possível, é recomendável definir o cabeçalho Timing-Allow-Origin
para que suas métricas sejam mais precisas.
Como o layout e as mudanças de tamanho dos elementos são processados?
Para manter o overhead de performance do cálculo e envio de novas entradas de performance baixo, as mudanças no tamanho ou na posição de um elemento não geram novos candidatos de LCP. Apenas o tamanho e a posição inicial do elemento na viewport são considerados.
Isso significa que as imagens que são renderizadas inicialmente fora da tela e depois passam para a tela podem não ser relatadas. Isso também significa que os elementos renderizados inicialmente na viewport que são empurrados para baixo, fora da visualização, ainda vão informar o tamanho inicial na viewport.
Exemplos
Confira alguns exemplos de quando o Largest Contentful Paint ocorre em alguns sites populares:
Nas duas linhas do tempo acima, o elemento maior muda conforme o conteúdo é carregado. No primeiro exemplo, um novo conteúdo é adicionado ao DOM e isso altera o elemento que é o maior. No segundo exemplo, o layout muda e o conteúdo que era o maior é removido da janela de visualização.
Embora o conteúdo de carregamento tardio seja geralmente maior do que o que já está na página, nem sempre é assim. Os dois exemplos a seguir mostram o LCP ocorrendo antes do carregamento completo da página.
No primeiro exemplo, o logotipo do Instagram é carregado relativamente cedo e continua sendo o maior elemento, mesmo quando outros conteúdos são mostrados progressivamente. No exemplo da página de resultados da Pesquisa Google, o maior elemento é um parágrafo de texto que é exibido antes de qualquer imagem ou logotipo terminar de carregar. Como todas as imagens individuais são menores que este parágrafo, ele continua sendo o maior elemento durante o processo de carregamento.
Como medir a LCP
O LCP pode ser medido no laboratório ou no campo, e está disponível nas seguintes ferramentas:
Ferramentas de campo
- Relatório de experiência do usuário do Chrome
- PageSpeed Insights
- Search Console (relatório de Core Web Vitals)
- Biblioteca JavaScript
web-vitals
Ferramentas do laboratório
Medir o LCP no JavaScript
Para medir a LCP em JavaScript, use a API Largest Contentful Paint. O exemplo a seguir mostra como criar um PerformanceObserver
que detecta entradas largest-contentful-paint
e as registra no console.
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}
}).observe({type: 'largest-contentful-paint', buffered: true});
No exemplo acima, cada entrada largest-contentful-paint
registrada representa o candidato atual da LCP. Em geral, o valor startTime
da última entrada emitida é o valor da LCP, mas nem sempre é assim. Nem todas as entradas de largest-contentful-paint
são válidas para medir a LCP.
A seção a seguir lista as diferenças entre o que a API informa e como a métrica é calculada.
Diferenças entre a métrica e a API
- A API vai enviar entradas
largest-contentful-paint
para páginas carregadas em uma guia em segundo plano, mas essas páginas precisam ser ignoradas ao calcular o LCP. - A API vai continuar a enviar entradas
largest-contentful-paint
depois que uma página for enviada para o segundo plano, mas essas entradas serão ignoradas ao calcular o LCP. Os elementos só serão considerados se a página estiver em primeiro plano o tempo todo. - A API não informa entradas
largest-contentful-paint
quando a página é restaurada do cache de avanço e retorno, mas a LCP precisa ser medida nesses casos, porque os usuários as utilizam como visitas distintas à página. - A API não considera elementos em iframes, mas a métrica sim, porque eles fazem parte da experiência do usuário na página. Em páginas com um LCP em um iframe, por exemplo, uma imagem de pôster em um vídeo incorporado, isso vai aparecer como uma diferença entre o CrUX e o RUM. Considere-as para medir corretamente a LCP. Os subframes podem usar a API para informar as entradas
largest-contentful-paint
para o frame pai para agregação. - A API mede a LCP desde o início da navegação, mas, para páginas pré-renderizadas, a LCP precisa ser medida usando
activationStart
, já que corresponde ao tempo de LCP conforme a experiência do usuário.
Em vez de memorizar todas essas diferenças sutis, os desenvolvedores podem usar a biblioteca JavaScript web-vitals
para medir o LCP, que processa essas diferenças para você (quando possível, o problema do iframe não é coberto):
import {onLCP} from 'web-vitals';
// Measure and log LCP as soon as it's available.
onLCP(console.log);
Consulte o código-fonte de onLCP()
(em inglês) para um exemplo completo de como medir a LCP em JavaScript.
E se o elemento maior não for o mais importante?
Em alguns casos, o elemento (ou elementos) mais importante da página não é o mesmo que o maior, e os desenvolvedores podem estar mais interessados em medir os tempos de renderização desses outros elementos. Isso é possível usando a API Element Timing, conforme descrito no artigo sobre métricas personalizadas.
Como melhorar a LCP
Um guia completo sobre como otimizar o LCP está disponível para orientar você no processo de identificação dos tempos de LCP no campo e de uso de dados de laboratório para detalhar e otimizar.
Outros recursos
- Lições aprendidas com a monitoração de desempenho no Chrome, por Annie Sullivan, em performance.now() (2019)
Registro de alterações
Às vezes, eles são descobertos nas APIs usadas para medir as métricas e, às vezes, nas definições das próprias métricas. Como resultado, às vezes é necessário fazer mudanças, que podem aparecer como melhorias ou regressões nos seus relatórios e painéis internos.
Para ajudar você a gerenciar isso, todas as mudanças na implementação ou definição dessas métricas serão exibidas no Registro de alterações.
Se você tiver feedback sobre essas métricas, envie-o no grupo de feedback do Web Vitals no Google.