Historicamente, os desenvolvedores da Web têm dificuldade 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 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 nas discussões no Grupo de trabalho de desempenho da Web do W3C e nas 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 elemento maior é 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 até a página pela primeira vez.
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ísticas para excluir determinados elementos que os usuários provavelmente consideram "sem conteúdo". Para navegadores baseados no Chromium, eles incluem:
- 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 essa heurística para corresponder às expectativas dos usuários sobre qual é o maior elemento contentful.
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. Embora ambas usem "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 viewport ou se qualquer parte dele for cortada ou tiver overflow não visível, essas partes não serão consideradas 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 fazer referência à <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 à medida que o novo conteúdo fica disponível. 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 vai continuar sendo o maior, a menos que um 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 são tratadas as mudanças de layout e tamanho dos elementos?
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 inicialmente renderizadas fora da tela e depois transferidas para a tela podem não ser informadas. 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
Aqui estão alguns exemplos de quando a Maior exibição de conteúdo 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 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.
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 de laboratório
- Chrome DevTools
- Farol
- PageSpeed Insights
- WebPageTest (em inglês)
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 o 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 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 de
largest-contentful-paint
quando a página é restaurada do cache de ida/volta, mas o LCP precisa ser medido nesses casos, já que os usuários os consideram como visitas a páginas distintas. - A API não considera os elementos dos iframes, mas a métrica faz isso, já que eles fazem parte da experiência do usuário na página. Em páginas com uma LCP em um iframe, como 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
ao frame pai para agregação. - A API mede o LCP desde o início da navegação, mas, para páginas pré-renderizadas, o LCP precisa ser medido a partir de
activationStart
, já que isso corresponde ao tempo de LCP percebido pelo 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()
para conferir um exemplo completo de como medir o LCP no 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 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, são descobertos bugs nas APIs usadas para medir métricas e, às vezes, nas definições das 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 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.