Forced reflow no Lighthouse: o que significa e como corrigir

Um script que altera a página e pede um tamanho logo depois faz o navegador refazer o layout na mesma hora. Quando isso faz os toques travarem e quando é inofensivo.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-10-26

O que significa Forced reflow no Lighthouse?

Um forced reflow significa que um script alterou a página e pediu um tamanho logo depois, obrigando o navegador a recalcular o layout na mesma hora. O Lighthouse lista esses scripts no insight Forced reflow ("A forced reflow occurs when JavaScript queries geometric properties"). Acontecer uma vez é normal; em um loop, faz os toques travarem. Deixe o CSS fazer o trabalho do script ou leia todos os tamanhos antes de alterar qualquer coisa.

O que o aviso de Forced reflow lista?

O Lighthouse 13 e o PageSpeed Insights descrevem isso assim: "A forced reflow occurs when JavaScript queries geometric properties (such as offsetWidth) after styles have been invalidated by a change to the DOM state. This can result in poor performance. Learn more about forced reflows and possible mitigations." O aviso fica vermelho quando scripts forçam 30 ms ou mais de trabalho de layout de uma só vez durante o carregamento da página.

O relatório abaixo vem de uma página de listagem de chalés que criei como um site de aluguel por temporada em WordPress, onde o script do tema corta cada descrição para três linhas e deixa todos os cards com a mesma altura.

Lighthouse 13.5 report, the Forced reflow insight expanded with the label Unscored: Top function call cabins.js line 46, 388 ms; Source rows cabins.js line 10 3 ms, line 12 733 ms, line 23 7 ms

Lighthouse 13.5 no celular, throttling do DevTools (Slow 4G, 4x CPU).

  • Top function call: a função externa que iniciou o trabalho de layout. Passe o cursor sobre o caminho encurtado do arquivo para ver o caminho completo, que identifica o tema, plugin ou app. Um arquivo em outro domínio geralmente é uma tag de terceiros, como um gravador de sessão (Scripts que você não pode alterar).
  • Source: cada linha de código que pediu um tamanho.
  • Total reflow time: o tempo de layout causado por essa função ou linha.
  • Unscored: o insight não tem peso na pontuação de Performance. As long tasks por trás dele (intervalos acima de 50 ms nos quais a página não consegue responder) reduzem a pontuação pelo Total Blocking Time.

A linha superior (388 ms) é menor que a soma das linhas de Source (743 ms) porque o script dos chalés executa duas vezes durante o carregamento, e a linha superior mostra apenas a maior execução.

Por que um script força o navegador a refazer o layout?

Na listagem de chalés acima, um toque no filtro "All" congela a página por um terço de segundo antes de os 48 cards aparecerem.

O layout é a etapa em que o navegador calcula onde cada caixa fica e qual é o seu tamanho. Ele normalmente faz isso uma vez por frame, depois que os scripts são executados. Quando um script altera a página (um texto, uma classe, uma altura) e depois lê um tamanho, como offsetHeight, getBoundingClientRect(), scrollTop ou getComputedStyle(), o navegador precisa fazer o layout na hora, dentro do script, para responder. O Paul Irish mantém a lista completa das leituras que forçam isso.

Um único forced reflow é, na maior parte, trabalho de layout que o navegador faria um instante depois. Em um loop que altera e lê de novo, acontece um layout completo a cada iteração: layout thrashing. O tema dos chalés corta cada descrição assim:

while (el.offsetHeight > max && words.length > 1) {
  words.pop();
  el.textContent = words.join(' ') + '…';
}

Cada palavra removida altera o texto, então a leitura seguinte de offsetHeight força um novo layout: um por palavra, em cada card.

Quanto um forced reflow deixa a página mais lenta?

Medi a listagem de chalés com o script do tema (Antes) e com CSS cortando o texto e igualando a altura dos cards (Depois). As duas versões têm a mesma aparência.

AntesDepois
Pontuação no Lighthouse8492
Total Blocking Time360 ms0 ms
Total reflow time743 msnenhum
Um toque em "All"320 ms16 ms
Lighthouse report at phone width for the cabin listing before the fix: Performance 84, First Contentful Paint 2.7 s, Largest Contentful Paint 2.7 s, Total Blocking Time 360 ms, CLS 0

Antes

The same report after the fix: Performance 92, First Contentful Paint 2.7 s, Largest Contentful Paint 2.7 s, Total Blocking Time 0 ms, CLS 0

Depois

Lighthouse 13.5 no celular, throttling do DevTools.

Os 8 pontos vêm do Total Blocking Time: os layouts forçados mantêm a página bloqueada por mais tempo. O toque é o que o visitante percebe, e conta para o INP (Interaction to Next Paint), o Core Web Vital que mede a rapidez com que a página responde a toques e cliques. 320 ms fica acima do limite de 200 ms para um bom INP, e 298 ms disso foi trabalho de layout forçado pelo script; 16 ms equivale a um único frame. O Lighthouse nunca toca na tela, então medi os toques no Chrome com a CPU desacelerada para a velocidade de um celular.

Quando um forced reflow é inofensivo?

  • Uma linha pequena durante o carregamento. Uma linha pouco acima de 30 ms costuma ser o primeiro layout da página, adiantado um pouco porque um script pediu um tamanho. O script de tema da listagem de chalés, reescrito para ler todas as alturas primeiro, mostrou uma linha de 37 ms em uma de quatro execuções do Lighthouse, e o toque em "All" levou 16 ms.
  • Uma linha "[unattributed]". Ela não indica nenhuma linha de código: execute o Lighthouse novamente e, se a linha sumir, deixe como está.
  • Um script que inicia uma animação. Modais do Bootstrap e alguns plugins de popup leem um tamanho de propósito para que a transição CSS deles comece.
Forced reflow insight with one row: Top function call cabins.js line 29, 37 ms, and one Source row cabins.js line 8, 37 ms

Lighthouse 13.5 no celular, throttling do DevTools.

Corrija quando o total reflow time estiver na casa das centenas de milissegundos, quando um mesmo arquivo tiver várias linhas ou quando o script também rodar em toques: um filtro, um menu, um slider.

Qual script causa o forced reflow em um toque?

O Lighthouse apenas carrega a página, então grave no painel Performance os toques que travam:

  1. Abra o DevTools (F12), vá em Performance e ajuste a CPU para 4x slowdown, para que seu notebook se comporte como um celular.
  2. Clique em Record, toque no que parece lento e pare a gravação.
  3. Abra Forced reflow na barra lateral Insights. "Call frames that trigger reflow" indica a função e a linha.
Chrome DevTools Performance panel with one tap recorded: the Main track shows Event: click, filterCards, layoutCards and clampText over a long row of layout work; the Forced reflow insight in the sidebar lists 452 ms and the call frames clampText in cabins.js lines 10 and 12

Um toque em "All" na listagem de chalés: clampText em cabins.js.

O console relata a mesma coisa como "[Violation] Forced reflow while executing JavaScript took 38ms", assim que você ativa Verbose nos níveis de log.

Quando o Lighthouse cita apenas jquery.min.js, o jQuery fez a leitura no lugar de um tema ou plugin. Grave um recarregamento no painel Performance e clique em um bloco de Layout com triângulo vermelho: sob Function stack no Summary, o arquivo entre as linhas do jQuery, com um caminho como /wp-content/plugins/<name>/, é o plugin.

Os field data registram os toques e cliques dos visitantes reais. No CoreDash, abra INP, Breakdown e agrupe por LOAF: o Chrome registra quais scripts rodaram em cada frame lento (Long Animation Frames), então cada linha é um script com o INP das interações em que ele executou. Um forced reflow em um handler de clique ou toque conta como processing, a parte roxa de cada barra, então comece por um script lento cuja parte roxa seja longa.

CoreDash INP subparts by LOAF: p75 INP per script, from 125 ms (good) to 0.65 s (poor), each split into input delay, processing and presentation.

INP por script no CoreDash, desktop, p75: verde é input delay, roxo processing, azul presentation.

Como corrigir um forced reflow?

Comece pelo arquivo indicado em Top function call e veja se o CSS pode fazer o trabalho do script. Texto cortado em três linhas (line-clamp), cards com a mesma altura (grid), cabeçalho fixo no topo (position: sticky) e caixa de imagem que mantém as proporções (aspect-ratio) não precisam de script. Sem o script, nada força o layout.

Depois de aplicar qualquer correção abaixo, grave o mesmo toque de novo: Forced reflow deve ter sumido da barra lateral Insights. Em seguida, verifique no Lighthouse e nos field data; o Search Console leva até 28 dias.

Temas, plugins e page builders do WordPress

O caminho em Top function call indica o tema (/wp-content/themes/) ou o plugin (/wp-content/plugins/). Procure primeiro por uma configuração. A opção "Stretch Section" do Elementor alarga uma seção com JavaScript a cada carregamento e resize; o layout de página Elementor Full Width com um container de largura total faz isso com CSS. Um slider Swiper configurado com "auto" em slides per view mede cada slide; com um número fixo, ele calcula as larguras sem precisar lê-las.

Adiar o JavaScript no WP Rocket ou em um plugin parecido elimina o aviso, mas o script passa a rodar no primeiro toque ou scroll do visitante, com os mesmos layouts forçados. Em vez disso, corrija o script ou relate o problema ao desenvolvedor do plugin e troque de plugin se nada mudar.

Quando o tema cortar texto com JavaScript, corte com CSS no child theme, usando a classe de texto do tema:

.cabin .desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

Depois, desative o script de clamp do tema: por uma opção do tema ou com wp_dequeue_script() usando o handle dele.

Temas e apps da Shopify

No editor de temas, em App embeds, desative os apps um por um e execute o Lighthouse novamente. Quando o aviso sumir, relate o problema ao desenvolvedor desse app ou substitua o app. Um caminho com /assets/ em Top function call é um arquivo do tema, seja do próprio tema ou de um app que inseriu código nele. O Dawn e os temas baseados nele costumam ler o tamanho uma única vez e agrupar as alterações em lote; portanto, olhe os apps primeiro.

JavaScript próprio e React

Quando um script precisa medir, leia todos os tamanhos primeiro e faça as alterações depois, para que um único layout atenda a todas as leituras. Veja um accordion que ajusta cada painel à sua própria altura:

const panels = [...document.querySelectorAll('.panel')];

// A layout for every panel: read, write, read, write
panels.forEach(p => { p.style.maxHeight = p.scrollHeight + 'px'; });

// One layout: read every height, then write them all
const heights = panels.map(p => p.scrollHeight);
panels.forEach((p, i) => { p.style.maxHeight = heights[i] + 'px'; });
  • Resize e scroll: ResizeObserver e IntersectionObserver entregam os tamanhos a partir do layout que o navegador acabou de fazer. Use-os em vez de ler tamanhos em um handler de resize ou scroll.
  • React: meça uma única vez no useLayoutEffect e atualize o estado uma só vez. Monte menus, popovers e tooltips quando eles abrirem, para que os elementos fechados não meçam nada durante o carregamento.

Scripts que você não pode alterar

Gravadores de sessão e tags de mapa de calor leem tamanhos de propósito: o Microsoft Clarity lê uma dúzia de tamanhos de página ao iniciar e a posição de tudo o que um visitante clica. Remova a tag, grave uma amostragem das visitas ou carregue o script apenas nas páginas que você estiver analisando.

Forced reflow em um plugin ou app que você não consegue substituir, ou toques que travam no celular dos visitantes e não no seu? Em uma Core Web Vitals power hour, encontramos o script por trás dos toques mais lentos e decidimos juntos se o caminho é corrigir, substituir ou remover.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

 

Search Console reclamou do seu site?

Entrego uma lista priorizada de fixes baseada em dados de campo. Não um PDF de 50 páginas.

Solicitar auditoria
Forced reflow no Lighthouse: o que significa e como corrigir Core Web Vitals Forced reflow no Lighthouse: o que significa e como corrigir