Saiba como identificar e corrigir mudanças de layout.
A primeira parte deste artigo discute as ferramentas para depurar mudanças de layout, enquanto a segunda parte discute o processo de pensamento a ser usado ao identificar a causa de uma mudança de layout.
Ferramentas
API Layout Instability
A API Layout Instability é o mecanismo do navegador para medir e relatar mudanças de layout. Todas as ferramentas para depurar mudanças de layout, incluindo o DevTools, são criadas com base na API Layout Instability. No entanto, usar a API Layout Instability de forma direta é uma ferramenta de depuração poderosa devido à flexibilidade dela.
Uso
O mesmo snippet de código que mede a Mudança de layout cumulativa (CLS, na sigla em inglês) também pode depurar mudanças de layout. O snippet abaixo registra informações sobre mudanças de layout para o console. A inspeção desse registro fornecerá informações sobre quando, onde e como uma mudança de layout ocorreu.
let cls = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
console.log('Current CLS value:', cls, entry);
}
}
}).observe({type: 'layout-shift', buffered: true});
Ao executar esse script, lembre-se de que:
- A opção
buffered: true
indica que oPerformanceObserver
precisa verificar o buffer de entrada de desempenho do navegador em busca de entradas de desempenho que foram criadas antes da inicialização do observador. Como resultado, oPerformanceObserver
informa mudanças de layout que aconteceram antes e depois de ser inicializada. Lembre-se disso ao inspecionar os registros do console. Uma sobrecarga inicial de mudanças de layout pode refletir um backlog de relatórios, em vez da ocorrência repentina de várias mudanças de layout. - Para evitar impactos no desempenho, o
PerformanceObserver
aguarda até que a linha de execução principal esteja inativa para informar as mudanças de layout. Como resultado, dependendo da ocupação da linha de execução principal, pode haver um pequeno atraso entre o momento em que ocorre uma mudança de layout e o momento em que ela é registrada no console. - Esse script ignora as mudanças de layout que ocorreram dentro de 500 ms da entrada do usuário e, portanto, não são contabilizadas na CLS.
As informações sobre mudanças de layout são informadas usando uma combinação de duas APIs: as interfaces
LayoutShift
e
LayoutShiftAttribution
. Cada uma delas é explicada em mais detalhes nas
seções a seguir.
LayoutShift
Cada mudança de layout é informada usando a interface LayoutShift
. O conteúdo de uma entrada tem esta aparência:
duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798
A entrada acima indica uma mudança de layout durante a qual três elementos DOM mudaram de
posição. A pontuação dessa mudança de layout específica foi de 0.175
.
Estas são as propriedades de uma instância de LayoutShift
que são mais relevantes para
depurar mudanças de layout:
Propriedade | Descrição |
---|---|
sources |
A propriedade sources lista os elementos DOM que foram movidos durante a mudança de layout. Essa matriz pode conter até cinco origens. Caso mais de cinco elementos sejam afetados pela mudança de layout, as cinco maiores fontes de mudança de layout (medidas pelo impacto na estabilidade) serão informadas. Essas informações são relatadas usando a interface de Atribuição do LayoutShift (explicada em mais detalhes abaixo). |
value |
A propriedade value informa a pontuação da mudança de layout para uma determinada mudança de layout. |
hadRecentInput |
A propriedade hadRecentInput indica se uma mudança de layout ocorreu em até 500 milissegundos após a entrada do usuário. |
startTime |
A propriedade startTime indica quando ocorreu uma mudança de layout. startTime é indicado em milissegundos e é medido em relação ao tempo em que o carregamento da página foi iniciado. |
duration |
A propriedade duration sempre será definida como 0 . Essa propriedade é herdada da interface PerformanceEntry (a interface LayoutShift estende a interface PerformanceEntry ). No entanto, o conceito de duração não se aplica a eventos de mudança de layout. Por isso, ele é definido como 0 . Para mais informações sobre a interface PerformanceEntry , consulte a spec. |
LayoutShiftAttribution
A interface LayoutShiftAttribution
descreve uma única mudança de um único elemento DOM. Se vários elementos forem alterados durante uma mudança de layout, a propriedade sources
vai conter várias entradas.
Por exemplo, o JSON abaixo corresponde a uma mudança de layout com uma fonte: a
mudança para baixo do elemento DOM <div id='banner'>
de y: 76
para
y:246
.
// ...
"sources": [
{
"node": "div#banner",
"previousRect": {
"x": 311,
"y": 76,
"width": 4,
"height": 18,
"top": 76,
"right": 315,
"bottom": 94,
"left": 311
},
"currentRect": {
"x": 311,
"y": 246,
"width": 4,
"height": 18,
"top": 246,
"right": 315,
"bottom": 264,
"left": 311
}
}
]
A propriedade node
identifica o elemento HTML que mudou. Passe o cursor sobre essa
propriedade no DevTools para destacar o elemento de página correspondente.
As propriedades previousRect
e currentRect
informam o tamanho e a posição
do nó.
- As coordenadas
x
ey
informam a coordenada x e a coordenada y, respectivamente do canto superior esquerdo do elemento. - As propriedades
width
eheight
informam a largura e a altura do elemento, respectivamente. - As propriedades
top
,right
,bottom
eleft
informam os valores das coordenadas x ou y correspondentes à aresta do elemento especificada. Em outras palavras, o valor detop
é igual ay
, e o valor debottom
é igual ay+height
.
Se todas as propriedades de previousRect
forem definidas como 0, isso significa que o elemento
foi movido para visualização. Se todas as propriedades de currentRect
forem definidas como 0, isso significa
que o elemento foi movido para fora da visualização.
Uma das coisas mais importantes a se entender ao interpretar essas saídas é que os elementos listados como fontes são aqueles que mudaram durante a mudança de layout. No entanto, é possível que esses elementos estejam apenas indiretamente relacionados à "causa raiz" da instabilidade de layout. Veja alguns exemplos.
Exemplo 1
Essa mudança de layout seria informada com uma fonte: o elemento B. No entanto, a causa raiz dessa mudança de layout é a mudança de tamanho do elemento A.
Exemplo 2
A mudança de layout neste exemplo seria informada com duas origens: elemento A e elemento B. A causa raiz dessa mudança de layout é a mudança na posição do elemento A.
Exemplo 3
A mudança de layout neste exemplo seria informada com uma fonte: o elemento B. Mudar a posição do elemento B resultou nessa mudança de layout.
Exemplo 4
Embora o tamanho do elemento B mude, não há mudança de layout neste exemplo.
Confira uma demonstração de como as alterações do DOM são informadas pela API Layout Instability.
DevTools
Painel de desempenho
O painel Experiência do painel Desempenho do DevTools exibe todas as mudanças de layout que ocorrem durante um determinado rastreamento de desempenho, mesmo que elas ocorram até 500 ms após uma interação do usuário e, portanto, não sejam contabilizadas no CLS. Passe o cursor sobre uma mudança de layout específica no painel Experiência para destacar o elemento DOM afetado.
Para ver mais informações sobre a mudança de layout, clique nela e
abra a gaveta Summary. As mudanças nas dimensões do elemento são listadas
usando o formato [width, height]
. As mudanças na posição do elemento são listadas
usando o formato [x,y]
. A propriedade Had new input indica se uma
mudança de layout ocorreu em até 500 ms após uma interação do usuário.
Para mais informações sobre a duração de uma mudança de layout, abra a guia Event Log. A duração de uma mudança de layout também pode ser aproximada ao consultar o comprimento do retângulo vermelho de mudança de layout no painel Experiência.
Para saber mais sobre como usar o painel Performance, consulte a Referência de análise de desempenho.
Destacar regiões de mudança de layout
Destacar as regiões de mudança de layout pode ser uma técnica útil para ter uma ideia rápida e rápida da localização e do tempo das mudanças de layout ocorridas em uma página.
Para ativar as regiões de mudança de layout no DevTools, acesse Settings > More Tools > Rendering > Layout Shift Territory e atualize a página que você quer depurar. As áreas de mudança de layout serão brevemente destacadas em roxo.
Processo de pensamento para identificar a causa das mudanças de layout
Você pode usar as etapas abaixo para identificar a causa das mudanças de layout, independente de quando ou como elas ocorrem. Essas etapas podem ser complementadas com a execução do Lighthouse. No entanto, lembre-se de que o Lighthouse só pode identificar mudanças de layout que ocorreram durante o carregamento inicial da página. Além disso, o Lighthouse também só pode fornecer sugestões para algumas causas de mudanças de layout, por exemplo, elementos de imagem que não têm largura e altura explícitas.
Identificar a causa de uma mudança de layout
As mudanças de layout podem ser causadas pelos seguintes eventos:
- Alterações na posição de um elemento DOM
- Alterações nas dimensões de um elemento DOM
- Inserção ou remoção de um elemento DOM
- Animações que acionam o layout
Em particular, o elemento DOM imediatamente anterior ao elemento deslocado é o elemento com maior probabilidade de estar envolvido na "causa" da mudança de layout. Assim, ao investigar por que uma mudança de layout ocorreu, considere o seguinte:
- A posição ou as dimensões do elemento anterior mudaram?
- Um elemento DOM foi inserido ou removido antes do elemento deslocado?
- A posição do elemento deslocado foi alterada explicitamente?
Se o elemento anterior não causou a mudança de layout, continue sua pesquisa considerando outros elementos anteriores e próximos.
Além disso, a direção e a distância de uma mudança de layout podem fornecer dicas sobre a causa raiz. Por exemplo, uma grande mudança para baixo geralmente indica a inserção de um elemento DOM, enquanto uma mudança de layout de 1 px ou 2 px geralmente indica a aplicação de estilos CSS conflitantes ou o carregamento e a aplicação de uma fonte da Web.
![Diagrama mostrando uma mudança de layout causada por uma troca de fontes](https://web.dev/static/articles/debug-layout-shifts/image/diagram-showing-layout-s-60ec3d8c95616.png?authuser=6&hl=pt)
Estes são alguns dos comportamentos específicos que causam eventos de mudança de layout com mais frequência:
Mudanças na posição de um elemento (que não sejam causadas pelo movimento de outro elemento)
Esse tipo de alteração geralmente é resultado de:
- Folhas de estilo que são carregadas com atraso ou substituem estilos declarados anteriormente.
- Efeitos de animação e transição.
Alterações nas dimensões de um elemento.
Esse tipo de alteração geralmente é resultado de:
- Folhas de estilo que são carregadas com atraso ou substituem estilos declarados anteriormente.
- Imagens e iframes sem os atributos
width
eheight
que são carregados depois da renderização do "slot". - Blocos de texto sem atributos
width
ouheight
que trocam fontes depois que o texto é renderizado.
Inserir ou remover elementos DOM
Isso geralmente é resultado de:
- Inserção de anúncios e outras incorporações de terceiros
- Inserção de banners, alertas e modais.
- Rolagem infinita e outros padrões de UX que carregam mais conteúdo acima do conteúdo atual.
Animações que acionam o layout
Alguns efeitos de animação podem acionar
o layout. Um exemplo comum disso é quando elementos DOM são "animados" incrementando propriedades como top
ou left
em vez de usar a propriedade transform
do CSS. Leia Como criar animações CSS de alto desempenho
para mais informações.
Como reproduzir mudanças de layout
Não é possível corrigir mudanças de layout que não podem ser reproduzidas. Uma das coisas mais simples, mas mais eficazes, para ter uma noção melhor da estabilidade do layout é de 5 a 10 minutos para interagir com o site com o objetivo de acionar mudanças de layout. Mantenha o console aberto enquanto isso e use a API Layout Instability para gerar relatórios sobre mudanças de layout.
Para mudanças de layout difíceis de localizar, repita este exercício com
diferentes dispositivos e velocidades de conexão. Em especial, o uso de uma velocidade
de conexão mais lenta pode facilitar a identificação de mudanças de layout. Além disso,
é possível usar uma instrução debugger
para facilitar as mudanças de
layout.
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
debugger;
console.log('Current CLS value:', cls, entry);
}
}
}).observe({type: 'layout-shift', buffered: true});
Por fim, para problemas de layout que não são reproduzíveis no desenvolvimento, considere usar a API Layout Instability com a ferramenta de geração de registros de front-end de sua preferência para coletar mais informações sobre esses problemas. Confira o exemplo de código para acompanhar o maior elemento deslocado em uma página.