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. Além disso, 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 tiver uma tela de apresentação ou um indicador de carregamento, esse momento não será muito relevante para o usuário.
No passado, recomendamos métricas de desempenho como Primeira pintura significativa (FMP) e Índice de velocidade (SI) (ambos disponíveis no Lighthouse) para ajudar a capturar mais da experiência de carregamento após a pintura inicial. No entanto, essas métricas são complexas, difíceis de explicar e, muitas vezes, erradas, ou seja, 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 na 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 do maior bloco de texto ou imagem visível na janela de visualização, em relação ao momento em que o usuário navegou até a página pela primeira vez.
O que é uma boa pontuação de LCP?
Para oferecer uma boa experiência ao usuário, os sites precisam ter uma Maior exibição de conteúdo de 2,5 segundos ou menos. Para garantir que você alcance essa meta para a maioria dos usuários, um bom limite para medir é o 75o percentil de carregamentos de página, segmentado em dispositivos móveis e computadores.
Quais elementos são considerados?
Conforme especificado no campo Maior exibição de conteúdo API, os tipos de elementos considerados para a Maior exibição de conteúdo:
- Elementos
<img>
(o tempo de apresentação do primeiro frame é usado para conteúdo animado, como GIFs ou PNGs animados) - Elementos
<image>
em 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 ocorrer primeiro) - 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.
Observe que restringir os elementos a esse conjunto limitado foi intencional para manter as coisas simples no início. Outros elementos (como o suporte completo a <svg>
) podem ser adicionados no futuro, à medida que 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 opacidade 0 que são invisíveis ao usuário.
- Elementos que cobrem toda a janela de visualização e 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 verdadeiro conteúdo da página
É provável que os navegadores continuem aprimorando essas heurísticas para atender às expectativas dos usuários sobre qual é o maior elemento contentful.
Essas respostas A heurística pode ser diferente daquelas usadas pela First Contentful Paint (FCP), que podem considerar alguns desses elementos, como imagens de marcador de posição ou imagens de janela de visualização completas, mesmo que não possam ser candidatas à LCP. Apesar de ambos usarem a palavra "conteúdo" no nome delas, o objetivo dessas métricas é diferente. A FCP mede quando qualquer conteúdo é pintado na tela e na LCP quando o conteúdo principal é pintado. Portanto, a LCP pode 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 do tamanho intrínseco, o tamanho informado é o visível ou o intrínseco, o que for menor.
Para elementos de texto, a LCP considera apenas o menor retângulo que pode conter todos os nós de texto.
Para todos os elementos, a LCP não considera margens, paddings ou bordas aplicadas usando CSS.
Quando a LCP é informada?
As páginas da Web geralmente são carregadas em etapas e, como resultado, é possível que o maior elemento na página mude.
Para lidar com esse potencial de mudança, o navegador envia um PerformanceEntry
do tipo largest-contentful-paint
identificando o maior elemento com conteúdo assim que ele pinta o primeiro frame. No entanto, depois de renderizar os frames subsequentes, 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 inicialmente renderizar o texto. Nesse momento, o navegador envia uma entrada largest-contentful-paint
com uma propriedade element
que provavelmente faria 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 com conteúdo depois de ser renderizado e ficar 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 também não usam fontes da Web durante o período de bloqueio da fonte. Nesses casos, um elemento menor pode ser informado como o maior elemento de conteúdo, mas assim que o maior terminar a renderização, outra PerformanceEntry
será criada.
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 de 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 vai continuar sendo o maior, a menos que um maior seja renderizado.
O navegador deixará de informar novas entradas assim que o usuário interagir com a página (por um toque, rolagem ou pressionamento de tecla), já que a interação do usuário frequentemente altera o que é visível para o usuário (o que é especialmente verdadeiro com a rolagem).
Para fins de análise, informe somente o PerformanceEntry
enviado mais recentemente ao seu 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 (pois isso já está exposto por meio de muitas outras APIs da Web).
Isso pode levar a uma situação aparentemente impossível, em que a LCP é informada pelas APIs da Web como anteriores à FCP. Esse não é o caso, apenas aparece devido a essa restrição de segurança.
Sempre que possível, recomendamos definir o cabeçalho Timing-Allow-Origin
para melhorar a precisão das métricas.
Como são tratadas as mudanças de layout e tamanho dos elementos?
Para manter baixo o overhead de desempenho do cálculo e do envio de novas entradas de desempenho, as mudanças no tamanho ou na posição de um elemento não geram novos candidatos à LCP. Somente o tamanho e a posição iniciais do elemento na janela de visualização são considerados.
Isso significa que é possível que as imagens renderizadas fora da tela e depois transicionadas na tela não sejam relatadas. Isso também significa que elementos renderizados inicialmente na janela de visualização que, depois, são empurrados para baixo, fora de vista, ainda informam seu tamanho inicial na janela de visualização.
Exemplos
Aqui estão alguns exemplos de quando a Maior exibição de conteúdo ocorre em alguns sites populares:
![Linha do tempo da Largest Contentful Paint de cnn.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-fc43128e011aa.png?authuser=5&hl=pt-br)
![Linha do tempo da Largest Contentful Paint de techcrunch.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-3713e2f14970a.png?authuser=5&hl=pt-br)
Nas duas linhas do tempo acima, o maior elemento muda conforme o conteúdo é carregado. No primeiro exemplo, um novo conteúdo é adicionado ao DOM e isso muda o elemento que é o maior. No segundo exemplo, o layout muda, e o conteúdo que era anteriormente o maior é removido da janela de visualização.
Embora muitas vezes o conteúdo de carregamento tardio seja maior do que o conteúdo que já está na página, esse não é necessariamente o caso. Os próximos dois exemplos mostram a LCP ocorrendo antes do carregamento completo da página.
![Linha do tempo da Largest Contentful Paint de instagram.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-9bc403e812154.png?authuser=5&hl=pt-br)
![Linha do tempo da Largest Contentful Paint de google.com](https://web.dev/static/articles/lcp/image/largest-contentful-paint-6c5554de0eac7.png?authuser=5&hl=pt-br)
No primeiro exemplo, o logotipo do Instagram é carregado relativamente cedo e continua sendo o maior elemento, mesmo que outros conteúdos sejam 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, ela continua sendo o maior elemento durante todo o processo de carregamento.
Como medir a LCP
A LCP pode ser medida no laboratório ou em campo e está disponível nestas ferramentas:
Ferramentas de campo
- Chrome User Experience Report
- PageSpeed Insights
- Search Console (relatório de Core Web Vitals)
- Biblioteca JavaScript
web-vitals
Ferramentas do laboratório
Medir a LCP em 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 à LCP atual. Em geral, o valor startTime
da última entrada emitida é o valor da LCP. No entanto, esse nem sempre é o caso. 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 no cálculo da LCP. - A API vai continuar a enviar entradas
largest-contentful-paint
depois que uma página estiver em segundo plano, mas essas entradas precisam ser ignoradas ao calcular a LCP. Só é possível considerar elementos 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, já que os usuários as utilizam como visitas distintas à página. - A API não considera os elementos dos iframes, mas a métrica faz isso, porque eles fazem parte da experiência do usuário na página. Em páginas com uma LCP em um iframe, por exemplo, uma imagem de pôster em um vídeo incorporado, isso vai aparecer como uma diferença entre CrUX e 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
, porque 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 a LCP, que processa essas diferenças para você (quando possível). O problema com o iframe não é abordado:
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, os elementos mais importantes da página não são iguais ao maior, e os desenvolvedores podem estar mais interessados em medir os tempos de renderização desses outros elementos. Isso é possível com a API Element Timing, conforme descrito no artigo sobre métricas personalizadas.
Como melhorar a LCP
Um guia completo sobre como otimizar a LCP está disponível para orientar você no processo de identificação de tempos da LCP em campo e usar dados de laboratório para detalhar e otimizá-los.
Outros recursos
- Lições aprendidas com o monitoramento 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, é preciso fazer alterações algumas vezes e elas podem aparecer como melhorias ou regressões nos seus relatórios e painéis internos.
Para ajudar você a gerenciar isso, todas as alterações na implementação ou na definição dessas métricas serão exibidas neste registro de alterações.
Se você tiver feedback sobre essas métricas, envie no Grupo do Google web-vitals-feedback.