Layout Shift causado por transições CSS
Aprenda a encontrar e remover transições CSS que criam layout shifts

Layout Shift causado por transições CSS: Entendendo e mitigando o impacto
Cumulative Layout Shifts que são causados por transições CSS geralmente ocorrem cedo durante a fase de carregamento da página. Esses layout shifts não acontecem consistentemente, o que os torna difíceis de depurar.
Table of Contents!
Entendendo as transições CSS:
As transições CSS são uma ferramenta poderosa para animar a mudança de uma propriedade ao longo do tempo. Elas são comumente usadas para efeitos como desvanecimento (fading), deslizamento e redimensionamento de elementos em uma página da web. Os desenvolvedores podem definir efeitos de transição especificando a propriedade a ser transicionada, a duração da transição e a função de tempo (timing function) que rege a aceleração da transição.
Uma transição pode ter uma propriedade, duração, função de tempo (timing-function) e um atraso (delay). A forma abreviada de uma transição é assim:
/* propriedade | duração | timing-function | atraso */ transition: margin-right 4s ease-in-out 1s;
Layout Shifts: A consequência não intencional:
Layout shifts ocorrem quando elementos em uma página da web mudam de posição ou tamanho, fazendo com que outros elementos fluam novamente e o layout geral da página mude. Embora as transições CSS sejam projetadas para fornecer animações suaves, elas podem desencadear inadvertidamente layout shifts, levando a uma experiência de usuário chocante e perturbadora. As causas mais comuns de layout shifts durante transições CSS incluem mudanças nas dimensões, posição ou visibilidade dos elementos.
Cumulative Layout Shifts causados por transições CSS geralmente ocorrem quando um elemento acima da dobra (above-the-fold), como um menu de navegação, transiciona do seu primeiro estado (sem estilo) para o seu estado final (estilizado ou até oculto). Isso geralmente é uma consequência não intencional de propriedades de transição excessivamente amplas. Por exemplo, uma entrada de menu deve transicionar apenas a cor de fundo e, em vez da propriedade de transição 'background-color', 'all' foi escolhido. Isso levará não apenas a uma transição de fundo, mas em alguns casos também a uma transição de largura, altura ou até visibilidade durante o carregamento da página.
Dê uma olhada no exemplo abaixo. Ele demonstra um layout shift causado por transições CSS que ocorrem durante a fase de carregamento de uma página. Infelizmente, vejo esse padrão o tempo todo, e encontrar e corrigir esses tipos de problemas pode ser difícil.
Encontre e corrija transições CSS:
Para encontrar e corrigir todos os layout shifts causados por transições CSS, precisamos fazer um teste rápido. Primeiro, precisamos encontrar todas as transições CSS. Depois de fazer isso, precisamos garantir que a transição não altere a posição (width, height, margin, padding, visibility) de um elemento. Podemos fazer isso modificando ou desativando essas transições. Por fim, podemos testar o impacto dessas alterações e decidir de uma vez por todas se as transições CSS estão causando problemas de CLS.
Dica de Core Web Vitals: Cumulative Layout Shifts que são causados por transição CSS geralmente ocorrem cedo durante a fase de carregamento da página. Esses layout shifts não acontecem consistentemente, o que os torna difíceis de depurar. Desacelerar sua rede simulando um dispositivo móvel e desativando seu cache facilitará encontrá-los!
Passo 1: Encontre transições CSS
Encontrar transições CSS pode ser feito manualmente: inspecione todas as folhas de estilo e pesquise a palavra 'transition'. Isso não deve dar mais de 10 minutos de trabalho, mas há uma maneira melhor! Basta colar este trecho (snippet) no console e pressionar enter
(() => {
let nodeTable = [];
let nodeArray = [];
// Obter o nome do nó
function getName(node) {
const name = node.nodeName;
return node.nodeType === 1
? name.toLowerCase()
: name.toUpperCase().replace(/^#/, '');
}
// Obter o seletor
const getSelector = (node) => {
let sel = '';
try {
while (node && node.nodeType !== 9) {
const el = node;
const part = el.id
? '#' + el.id
: getName(el) +
(el.classList &&
el.classList.value &&
el.classList.value.trim() &&
el.classList.value.trim().length
? '.' + el.classList.value.trim().replace(/\s+/g, '.')
: '');
if (sel.length + part.length > (100) - 1) return sel || part;
sel = sel ? part + '>' + sel : part;
if (el.id) break;
node = el.parentNode;
}
} catch (err) {
// Fazer nada...
}
return sel;
};
const getNodesWithTransition = (node) => {
// Obter o estilo computado
let cs = window.getComputedStyle(node);
let tp = cs['transition-property'];
let td = cs['transition-duration'];
// Se houver uma transição, adicione-a à tabela
if (tp !== '' && tp !== 'none' && td != '0s') {
nodeTable.push({ selector: getSelector(node), transition: cs['transition'] });
nodeArray.push(node);
}
// Chamar recursivamente esta função para cada nó filho
for (let i = 0; i < node.children.length; i++) {
getNodesWithTransition(node.children[i]);
}
}
// encontrar todas as transições
getNodesWithTransition(document.body);
// Exibir os resultados no console
console.log('%cTabela legível de seletores e suas transições', 'color: red; font-weight: bold;');
console.table(nodeTable);
console.log('%cNodeList para você inspecionar (mais difícil de ler, mas com mais informações)', 'color: red; font-weight: bold;');
console.log(nodeArray);
// estilos para substituir temporariamente as transições
let selectors = nodeTable.map((item) => item.selector).join(', ');
console.log('%cCSS específico para desativar todas as transições nesta página', 'color: red; font-weight: bold;');
console.log(`<style>${selectors}{transition-property: none !important;}</style>`);
console.log('%cCSS global para desativar todas as transições nesta página (não sugerido em produção)', 'color: red; font-weight: bold;');
console.log(`<style>*{transition-property: none !important;}</style>`);
})()
Ele mostrará uma tabela com todas as transições, os elementos em que estão trabalhando e mais detalhes sobre as transições.

Para encontrar layout shift, nós precisamos procurar por propriedades de transição como width,height, margin,padding, transform, display e especialmente all (já que all inclui todas as propriedades de transição válidas)
Passo 2: Modifique transições CSS
O trecho de JavaScript acima mostrará todas as transições, bem como fornecerá um código de exemplo sobre como desativar essas transições. Para fins de testes rápidos, sugiro seguir o caminho mais fácil e desativar todas as transições com uma simples linha de código CSS
<style>*{transition-property: none !important;}</style>É claro que para ambientes de produção, um pouco mais de sutileza é necessária. Cuidadosamente, remova apenas as propriedades de transição desnecessárias com base no seletor. Por exemplo, altere #button{transition: all .2s} para #button{transition: background-color .2s}
Passo 3: Meça a alteração no layout shift

Outras boas práticas de transição:
- Prefira Aceleração de GPU: Utilizar a aceleração de GPU para transições CSS pode descarregar a carga de trabalho de renderização da CPU para a GPU. Isso pode ser alcançado garantindo que as propriedades que estão sendo transicionadas sejam propícias à aceleração de GPU, como opacity e transform.
- Use a propriedade "will-change": A propriedade CSS
will-changeinforma ao navegador que um elemento específico provavelmente será alterado, permitindo que ele otimize a renderização de acordo. - Garanta Dimensões Consistentes: Para evitar layout shifts causados por mudanças nas dimensões, certifique-se de que os elementos tenham dimensões consistentes antes e depois da transição. Isso pode envolver definir dimensões explícitas, usar valores baseados em porcentagem ou empregar técnicas como caixas de proporção (aspect ratio boxes).
- Otimize as Funções de Tempo (Timing Functions): A escolha da função de tempo pode impactar significativamente a percepção de suavidade durante uma transição. Esteja ciente dos padrões de aceleração e desaceleração e considere usar
ease-in-outou funções cubic bezier personalizadas para uma sensação mais natural.
Search Console flagged your site?
When Google flags your Core Web Vitals you need a clear diagnosis fast. I deliver a prioritized fix list within 48 hours.
Request Urgent Audit
