Otimizar a Mudança de layout cumulativa

Aprenda a evitar mudanças repentinas no layout para melhorar a experiência do usuário

A Cumulative Layout Shift (CLS) é uma das três métricas do Core Web Vitals. Ele mede a instabilidade do conteúdo combinando a quantidade de conteúdo visível que mudou na janela de visualização com a distância que os elementos afetados se moveram.

As mudanças de layout podem distrair os usuários. Imagine que você começou a ler um artigo e, de repente, os elementos mudaram na página, fazendo você se perder e precisar encontrar o lugar de novo. Isso é muito comum na Web, inclusive ao ler notícias ou tentar clicar nos botões "Pesquisar" ou "Adicionar ao carrinho". Essas experiências são visualmente irritantes e frustrantes. Elas geralmente são causadas quando elementos visíveis são forçados a se mover porque outro elemento foi adicionado ou redimensionado de repente.

Para oferecer uma boa experiência ao usuário, os sites devem ter uma CLS de 0,1 ou menos em pelo menos 75% dos acessos à página.

Bons valores de CLS estão abaixo de 0,1, valores ruins são maiores do que 0,25 e tudo entre eles precisa ser melhorado
Valores de CLS bons são 0,1 ou menos. Os valores ruins são maiores que 0,25.

Ao contrário das outras Core Web Vitals, que são valores baseados em tempo medidos em segundos ou milissegundos, a pontuação de CLS é um valor sem unidade de acordo com o cálculo da quantidade de conteúdo que está mudando e a distância que ele percorre.

Neste guia, vamos abordar a otimização de causas comuns de mudanças de layout.

As causas mais comuns de uma CLS ruim são:

  • Imagens sem dimensões.
  • Anúncios, incorporações e iframes sem dimensões.
  • Conteúdo injetado dinamicamente, como anúncios, incorporações e iframes sem dimensões.
  • Fontes da Web.

Entender as causas das mudanças de layout

Antes de começar a procurar soluções para problemas comuns de CLS, é importante entender sua pontuação de CLS e de onde vêm as mudanças.

CLS em ferramentas de laboratório versus campo

É comum ouvir desenvolvedores dizerem que o CLS medido pelo Relatório de UX do Chrome (CrUX) está incorreto porque não corresponde ao CLS medido usando o Chrome DevTools ou outras ferramentas de laboratório. Ferramentas de laboratório de desempenho da Web, como o Lighthouse, podem não mostrar o CLS completo de uma página, porque normalmente fazem um carregamento simples da página para medir algumas métricas de desempenho da Web e fornecer algumas orientações. No entanto, os fluxos de usuários do Lighthouse permitem que você meça além da auditoria de carregamento de página padrão.

O CrUX é o conjunto de dados oficial do programa Core Web Vitals. Por isso, o CLS é medido durante toda a vida da página, e não apenas durante o carregamento inicial que as ferramentas de laboratório normalmente medem.

Mudanças de layout são muito comuns durante o carregamento da página, porque todos os recursos necessários são buscados para renderizar a página inicialmente, mas elas também podem acontecer após o carregamento inicial. Muitas mudanças pós-carregamento podem ocorrer como resultado de uma interação do usuário e, portanto, serão excluídas da pontuação de CLS porque são mudanças esperadas, desde que ocorram dentro de 500 milissegundos após a interação.

No entanto, outras mudanças pós-carregamento inesperadas pelo usuário podem ser incluídas quando não há interação qualificada. Por exemplo, se você rolar mais na página e o conteúdo de carregamento lento for carregado, isso vai causar mudanças. Outras causas comuns de CLS pós-carregamento são em interações de transições, por exemplo, em aplicativos de página única, que levam mais do que o período de carência de 500 milissegundos.

O PageSpeed Insights mostra o CLS percebido pelo usuário de um URL na seção "Descubra o que seus usuários reais estão enfrentando" e o CLS de carga baseada em laboratório na seção "Diagnosticar problemas de desempenho". As diferenças entre esses valores provavelmente são resultado de CLS pós-carregamento.

Captura de tela do PageSpeed Insights mostrando dados no nível do URL destacando o CLS real do usuário, que é consideravelmente maior que o CLS do Lighthouse
Neste exemplo, o CrUX mede um CLS muito maior do que o Lighthouse.

Identificar problemas de CLS de carga

Quando as pontuações de CLS do CrUX e do Lighthouse no PageSpeed Insights estão alinhadas, geralmente isso indica que há um problema de CLS de carregamento detectado pelo Lighthouse. Nesse caso, o Lighthouse vai ajudar com duas auditorias para fornecer mais informações sobre imagens que causam CLS devido à falta de largura e altura e também listar todos os elementos que mudaram para o carregamento da página junto com a contribuição de CLS. Para conferir essas auditorias, filtre as auditorias de CLS:

Captura de tela do Lighthouse mostrando as auditorias de CLS que fornecem mais informações para ajudar a identificar e resolver problemas de CLS
Diagnósticos detalhados de CLS do Lighthouse.

O painel de desempenho no DevTools também destaca as mudanças de layout na seção Experiência. A visualização Resumo de um registro Layout Shift inclui a pontuação cumulativa de mudança de layout e uma sobreposição de retângulo mostrando as regiões afetadas. Isso é útil para saber mais detalhes sobre problemas de CLS de carga, já que é fácil replicar com um perfil de desempenho de recarga.

Registros de deslocamento de layout exibidos no painel de desempenho do Chrome DevTools ao expandir a seção "Experiência"
Depois de gravar um novo rastro no painel "Performance", a seção Experiência dos resultados é preenchida com uma barra vermelha que mostra um registro Layout Shift. Ao clicar no registro, você pode detalhar os elementos afetados, mostrando detalhes como as entradas "movimentado de" e "movimentado para" nesta imagem.

Identificar problemas de CLS pós-carregamento

A discordância entre as pontuações de CLS do CrUX e do Lighthouse geralmente indica CLS pós-carregamento. Pode ser difícil acompanhar essas mudanças sem dados de campo. Para saber como coletar dados de campo, consulte Medir elementos de CLS no campo.

A extensão Métricas da Web do Chrome pode ser usada para monitorar a CLS enquanto você interage com uma página, seja em um aviso ou no console, onde é possível conferir mais detalhes sobre os elementos deslocados.

Como alternativa ao uso da extensão, você pode navegar na sua página da Web enquanto grava mudanças de layout usando um Observador de Desempenho colado no console.

Depois de configurar o monitoramento de mudança, tente replicar os problemas de CLS pós-carregamento. O CLS geralmente acontece enquanto o usuário rola uma página, quando o conteúdo carregado com lazy load é carregado totalmente sem espaço reservado para ele. O deslocamento do conteúdo quando o usuário mantém o ponteiro sobre ele é outra causa comum de CLS pós-carregamento. Qualquer mudança de conteúdo durante uma dessas interações é considerada inesperada, mesmo que ocorra em 500 milissegundos.

Para mais informações, consulte Como depurar mudanças de layout.

Depois de identificar as causas comuns de CLS, o modo de fluxo de usuário de períodos do Lighthouse também pode ser usado para garantir que os fluxos de usuários típicos não regressem com a introdução de mudanças de layout.

Medir os elementos de CLS no campo

Monitorar a CLS no campo pode ser muito útil para determinar em quais circunstâncias ela ocorre e restringir as possíveis causas. Como a maioria das ferramentas de laboratório, as ferramentas de campo medem apenas os elementos que mudaram, mas isso geralmente fornece informações suficientes para identificar a causa. Também é possível usar as medições de campo de CLS para determinar quais problemas têm a maior prioridade para correção.

A biblioteca web-vitals tem funções de atribuição que permitem coletar essas informações adicionais. Para mais informações, consulte Depurar o desempenho no campo. Outros provedores de RUM também começaram a coletar e apresentar esses dados de maneira semelhante.

Causas comuns de CLS

Depois de identificar as causas do CLS, você pode começar a corrigir os problemas. Nesta seção, vamos mostrar algumas das causas mais comuns de CLS e o que você pode fazer para evitá-las.

Imagens sem dimensões

Sempre inclua os atributos de tamanho width e height nos elementos de imagem e vídeo. Como alternativa, reserve o espaço necessário com CSS aspect-ratio ou algo semelhante. Essa abordagem garante que o navegador possa alocar a quantidade correta de espaço no documento enquanto a imagem está sendo carregada.

Imagens sem largura e altura especificadas.
Imagens com largura e altura especificadas.
Relatório do Lighthouse mostrando o impacto antes/depois do deslocamento cumulativo de layout após definir as dimensões nas imagens
Impacto do Lighthouse 6.0 na configuração das dimensões da imagem no CLS.

Histórico dos atributos width e height em imagens

Nos primeiros dias da Web, os desenvolvedores adicionavam atributos width e height às tags <img> para garantir que espaço suficiente fosse alocado na página antes que o navegador começasse a buscar imagens. Isso minimizaria o reflow e o relayout.

<img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons">

width e height neste exemplo não incluem unidades. Essas dimensões em pixels garantem que o navegador reserva uma área de 640 x 360 no layout da página. A imagem se estendia para caber nesse espaço, mesmo que as dimensões reais não correspondessem a ele.

Quando o Web design responsivo foi introduzido, os desenvolvedores começaram a omitir width e height e a usar o CSS para redimensionar imagens:

img {
  width: 100%; /* or max-width: 100%; */
  height: auto;
}

No entanto, como o tamanho da imagem não é especificado, o espaço não pode ser alocado para ela até que o navegador comece a fazer o download e possa determinar as dimensões. À medida que as imagens são carregadas, o texto é deslocado para baixo na página para abrir espaço para elas, criando uma experiência de usuário confusa e frustrante.

É aí que entra a proporção. A proporção de uma imagem é a relação entre a largura e a altura. É comum ver isso expresso como dois números separados por dois pontos (por exemplo, 16:9 ou 4:3). Para uma proporção x:y, a imagem tem x unidades de largura e y unidades de altura.

Isso significa que, se soubermos uma das dimensões, a outra pode ser determinada. Para uma proporção de 16:9:

  • Se puppy.jpg tiver uma altura de 360 px, a largura será 360 x (16 / 9) = 640 px.
  • Se puppy.jpg tiver 640 px de largura, a altura será 640 x (9 / 16) = 360 px.

Saber a proporção de uma imagem permite que o navegador calcule e reserve espaço suficiente para a altura e a área associada.

Práticas recomendadas modernas para definir dimensões de imagem

Como os navegadores modernos definem a proporção padrão das imagens com base nos atributos width e height de uma imagem, é possível evitar mudanças de layout definindo esses atributos na imagem e incluindo o CSS anterior na folha de estilo.

<!-- set a 640:360 i.e a 16:9 aspect ratio -->
<img src="puppy.jpg" width="640" height="360" alt="Puppy with balloons">

Todos os navegadores vão adicionar uma proporção padrão com base nos atributos width e height do elemento.

Isso calcula uma proporção com base nos atributos width e height antes do carregamento da imagem. Ela fornece essas informações logo no início do cálculo do layout. Assim que uma imagem é informada para ter uma determinada largura (por exemplo, width: 100%), a proporção é usada para calcular a altura.

Esse valor aspect-ratio é calculado pelos principais navegadores à medida que o HTML é processado, em vez de usar uma folha de estilo de user agent padrão (confira esta postagem para saber mais). Portanto, o valor é mostrado de maneira um pouco diferente. Por exemplo, o Chrome mostra isso na seção "Styles" do painel "Element":

img[Attributes Style] {
  aspect-ratio: auto 640 / 360;
}

O Safari se comporta de forma semelhante, usando uma fonte de estilo Atributos HTML. O Firefox não mostra essa aspect-ratio calculada no painel Inspector, mas a usa para o layout.

A parte auto do código anterior é importante porque faz com que as dimensões da imagem substituam a proporção padrão após o download da imagem. Se as dimensões da imagem forem diferentes, isso ainda causará alguma mudança no layout após o carregamento da imagem. No entanto, isso garante que a proporção ainda seja usada quando estiver disponível, caso o HTML esteja incorreto. Mesmo que a proporção real seja diferente do padrão, ela ainda causa menos deslocamento de layout do que o tamanho padrão de 0x0 de uma imagem sem dimensões fornecidas.

Para saber mais sobre a proporção e pensar melhor em imagens responsivas, confira o carregamento de página sem instabilidade com proporções de mídia.

Se a imagem estiver em um contêiner, use o CSS para redimensionar a imagem de acordo com a largura do contêiner. Definimos height: auto; para evitar o uso de um valor fixo para a altura da imagem.

img {
  height: auto;
  width: 100%;
}

E as imagens responsivas?

Ao trabalhar com imagens responsivas, srcset define as imagens que você permite que o navegador selecione e o tamanho de cada uma delas. Para garantir que os atributos de largura e altura de <img> possam ser definidos, cada imagem precisa usar a mesma proporção.

<img
  width="1000"
  height="1000"
  src="puppy-1000.jpg"
  srcset="puppy-1000.jpg 1000w, puppy-2000.jpg 2000w, puppy-3000.jpg 3000w"
  alt="Puppy with balloons"
/>

As proporções das imagens também podem mudar dependendo da direção de arte. Por exemplo, você pode incluir uma imagem cortada para janelas de visualização estreitas e mostrar a imagem completa em computadores:

<picture>
  <source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" />
  <source media="(min-width: 800px)" srcset="puppy-800w.jpg" />
  <img src="puppy-800w.jpg" alt="Puppy with balloons" />
</picture>

O Chrome, o Firefox e o Safari agora são compatíveis com a configuração de width e height nos elementos <source> de um determinado elemento <picture>:

<picture>
  <source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" width="480" height="400" />
  <source media="(min-width: 800px)" srcset="puppy-800w.jpg" width="800" height="400" />
  <img src="puppy-800w.jpg" alt="Puppy with balloons" width="800" height="400" />
</picture>

Anúncios, incorporações e outros conteúdos carregados tardiamente

As imagens não são o único tipo de conteúdo que pode causar mudanças de layout. Anúncios, incorporações, iframes e outros conteúdos injetados dinamicamente podem fazer com que o conteúdo que aparece depois deles seja deslocado para baixo, aumentando o CLS.

Os anúncios são um dos maiores responsáveis pelas mudanças de layout na Web. As redes de publicidade e os editores geralmente oferecem suporte a tamanhos de anúncios dinâmicos. Os tamanhos dos anúncios aumentam a performance/receita devido a taxas de cliques mais altas e mais anúncios competindo no leilão. Infelizmente, isso pode levar a uma experiência do usuário não ideal devido aos anúncios que empurram o conteúdo visível que você está vendo para baixo na página.

Com os widgets incorporáveis, você pode incluir conteúdo da Web portátil na sua página, como vídeos do YouTube, mapas do Google Maps e postagens de mídias sociais. No entanto, esses widgets geralmente não sabem o tamanho do conteúdo antes do carregamento. Como resultado, as plataformas que oferecem incorporações nem sempre reservam espaço para os widgets, o que causa mudanças no layout quando eles são carregados.

As técnicas para lidar com isso são semelhantes. As principais diferenças são o controle que você tem sobre o conteúdo que será inserido. Se isso for inserido por um terceiro, como um parceiro de publicidade, talvez você não saiba o tamanho exato do conteúdo que será inserido nem poderá controlar as mudanças de layout que acontecem nessas incorporações.

Reservar espaço para conteúdo de carregamento tardio

Ao colocar conteúdo de carregamento tardio no fluxo de conteúdo, é possível evitar mudanças de layout reservando o espaço para eles no layout inicial.

Uma abordagem é adicionar uma regra CSS min-height para reservar espaço ou, para conteúdo responsivo, como anúncios, por exemplo, usar a propriedade CSS aspect-ratio de maneira semelhante à maneira como os navegadores usam essa propriedade automaticamente para imagens com dimensões fornecidas.

Três dispositivos móveis com apenas conteúdo de texto no primeiro dispositivo, que é deslocado para baixo no segundo dispositivo, e a reserva de espaço com um marcador de posição, conforme mostrado no terceiro dispositivo, impede a mudança
Reservar espaço para anúncios pode evitar mudanças de layout

Talvez seja necessário considerar diferenças sutis nos tamanhos de anúncios ou marcadores em diferentes formatos usando consultas de mídia.

Para conteúdo que não tem uma altura fixa, como anúncios, pode não ser possível reservar a quantidade exata de espaço necessária para eliminar completamente a mudança de layout. Se um anúncio menor for veiculado, o editor poderá estilizar um contêiner maior para evitar mudanças no layout ou escolher o tamanho mais provável para o espaço do anúncio com base em dados históricos. A desvantagem dessa abordagem é que ela aumenta a quantidade de espaço em branco na página.

Em vez disso, defina o tamanho inicial como o menor que será usado e aceite um nível de deslocamento para conteúdo maior. O uso de min-height, como sugerido anteriormente, permite que o elemento pai cresça conforme necessário, reduzindo o impacto das mudanças de layout em comparação com o tamanho padrão de 0 px de um elemento vazio.

Evite recolher o espaço reservado mostrando um marcador de posição se, por exemplo, nenhum anúncio for retornado. Remover o espaço reservado para elementos pode causar tanto CLS quanto inserir conteúdo.

Colocar o conteúdo de carregamento tardio mais abaixo na janela de visualização

O conteúdo injetado dinamicamente mais perto da parte de cima da janela de visualização geralmente causa mudanças maiores no layout do que o conteúdo injetado mais para baixo na janela de visualização. No entanto, injetar conteúdo em qualquer lugar na janela de visualização ainda causa alguma mudança. Se não for possível reservar espaço para conteúdo injetado, recomendamos colocá-lo mais tarde na página para reduzir o impacto na CLS.

Evite inserir conteúdo novo sem uma interação do usuário

Provavelmente você já passou por mudanças de layout devido à interface que aparece na parte de cima ou de baixo da janela de visualização ao tentar carregar um site. Assim como nos anúncios, isso geralmente acontece com banners e formulários que deslocam o restante do conteúdo da página:

Conteúdo dinâmico sem espaço reservado.

Se você precisar mostrar esses tipos de recursos de interface, reserve espaço suficiente na viewport com antecedência (por exemplo, usando um marcador de posição ou uma interface de esqueleto) para que, quando for carregado, o conteúdo da página não se mova de forma inesperada. Como alternativa, sobreponha o conteúdo quando necessário para garantir que o elemento não faça parte do fluxo do documento. Consulte a postagem Práticas recomendadas para avisos de cookies para conferir mais recomendações sobre esses tipos de componentes.

Em alguns casos, adicionar conteúdo dinamicamente é uma parte importante da experiência do usuário. Por exemplo, ao carregar mais produtos em uma lista de itens ou ao atualizar o conteúdo do feed publicado. Há várias maneiras de evitar mudanças inesperadas no layout nesses casos:

  • Substitua o conteúdo antigo pelo novo em um contêiner de tamanho fixo ou use um carrossel e remova o conteúdo antigo após a transição. Desative todos os links e controles até que a transição seja concluída para evitar cliques ou toques acidentais enquanto o novo conteúdo é enviado.
  • Peça ao usuário para iniciar o carregamento de um novo conteúdo para que ele não se surpreenda com a mudança (por exemplo, com um botão "Carregar mais" ou "Atualizar"). É recomendável fazer uma pré-busca do conteúdo antes da interação do usuário para que ele apareça imediatamente. Vale lembrar que as mudanças de layout que ocorrem em até 500 milissegundos após a entrada do usuário não são contabilizadas na CLS.
  • Carregue o conteúdo fora da tela e sobreponha uma notificação para o usuário informando que ele está disponível (por exemplo, com um botão "Rolar para cima").
Exemplos de carregamento de conteúdo dinâmico sem causar mudanças inesperadas no layout do Twitter e do site da Chloé
Exemplos de carregamento de conteúdo dinâmico sem causar mudanças inesperadas no layout. À esquerda: conteúdo do feed ao vivo sendo carregado no Twitter. À direita: exemplo de "Carregar mais" no site da Chloé. Confira como a equipe do YNAP otimizou para CLS ao carregar mais conteúdo.

Animações

As mudanças nos valores de propriedade do CSS podem exigir que o navegador reaja a essas mudanças. Alguns valores, como box-shadow e box-sizing, acionam o redimensionamento, a pintura e a composição. Mudar as propriedades top e left também causa mudanças no layout, mesmo quando o elemento movido está na própria camada. Evite animar usando essas propriedades.

Outras propriedades do CSS podem ser alteradas sem acionar relayouts. Isso inclui o uso de animações transform para transladar, dimensionar, girar ou distorcer elementos.

Animações compostas que usam translate não podem afetar outros elementos e, portanto, não são contabilizadas para o CLS. Animações não compostas também não causam relayout. Para saber mais sobre quais propriedades do CSS acionam mudanças de layout, consulte Animações de alto desempenho.

Fontes da Web

O download e a renderização de fontes da Web geralmente são feitos de duas maneiras antes do download:

  • A fonte de fallback é trocada pela fonte da Web, resultando em um Flash of Unstyled Text (FOUT, na sigla em inglês).
  • O texto "invisível" é exibido usando a fonte substituta até que uma webfont esteja disponível e o texto seja mostrado (FOIT, "flash de texto invisível").

As duas abordagens podem causar mudanças de layout. Mesmo que o texto esteja invisível, ele ainda é exibido usando a fonte de fallback. Portanto, quando a fonte da Web é carregada, o bloco de texto e o conteúdo ao redor são movidos da mesma forma que a fonte visível.

As ferramentas a seguir podem ajudar a minimizar a mudança de texto:

  • font-display: optional pode evitar um novo layout, já que a fonte da Web só é usada se estiver disponível no momento do layout inicial.
  • Verifique se a fonte de substituição adequada é usada. Por exemplo, usar font-family: "Google Sans", sans-serif; garante que a fonte substituta sans-serif do navegador seja usada enquanto "Google Sans" é carregado. Se você não especificar uma fonte alternativa usando apenas font-family: "Google Sans", a fonte padrão será usada, que no Chrome é "Times", uma fonte serif que é uma correspondência pior do que a fonte sans-serif padrão.
  • Minimize as diferenças de tamanho entre a fonte substituta e a fonte da Web usando as novas APIs size-adjust, ascent-override, descent-override e line-gap-override, conforme detalhado na postagem Substitutos de fonte aprimorados.
  • A Font Load API pode reduzir o tempo necessário para criar as fontes necessárias.
  • Carregue as fontes da Web essenciais o mais rápido possível usando <link rel=preload>. Uma fonte pré-carregada terá mais chance de encontrar a first paint, em que não há mudança de layout.

Leia Práticas recomendadas para fontes para conferir outras práticas recomendadas relacionadas a fontes.

Reduza o CLS garantindo que as páginas sejam qualificadas para o bfcache

Uma técnica muito eficaz para manter as pontuações de CLS baixas é garantir que suas páginas da Web estejam qualificadas para o cache de ida/volta (bfcache).

O bfcache mantém as páginas na memória do navegador por um curto período após a navegação. Se você retornar a elas, elas serão restauradas exatamente como você as deixou. Isso significa que a página totalmente carregada fica disponível instantaneamente, sem os deslocamentos que normalmente ocorrem durante o carregamento devido a qualquer um dos motivos mencionados anteriormente.

Embora isso possa significar que o carregamento inicial da página encontre mudanças de layout, quando um usuário volta para as páginas, ele não vê as mesmas mudanças de layout repetidamente. Sempre evite as mudanças, mesmo na carga inicial, mas, quando isso for mais difícil de resolver, pelo menos reduza o impacto evitando-as em qualquer navegação do bfcache.

A navegação de ida e volta é comum em muitos sites. Por exemplo, voltar para uma página de conteúdo, de categoria ou de resultados da pesquisa.

Quando isso foi lançado no Chrome, vimos melhorias perceptíveis na CLS (links em inglês).

O bfcache é usado por padrão por todos os navegadores, mas alguns sites não estão qualificados para o bfcache por vários motivos. Leia o guia do bfcache para saber mais sobre como testar e identificar problemas que impedem o uso do bfcache para garantir que você está usando esse recurso totalmente e melhorando a pontuação geral de CLS do seu site.

Conclusão

Há várias técnicas para identificar e melhorar o CLS, conforme detalhado anteriormente neste guia. Existem permissões integradas às Core Web Vitals. Portanto, mesmo que não seja possível eliminar a CLS completamente, o uso de algumas dessas técnicas permitirá reduzir o impacto. Esperamos que isso permita que você fique dentro desses limites, criando uma experiência melhor para os usuários do seu site.