INP Presentation Delay: Tamanho do DOM, trabalho de layout e otimização de renderização

Aprenda como encontrar e melhorar problemas de INP causados pelo presentation delay

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-04

Problemas de Interaction to Next Paint (INP) causados pelo presentation delay

Esta página faz parte da nossa série sobre Interaction to Next Paint (INP). O INP mede o tempo total desde uma interação do usuário até a próxima atualização visual. O presentation delay é a terceira e última fase do INP, seguindo o input delay e o processing time. Se você é novo no INP, leia primeiro o nosso guia sobre como identificar e corrigir problemas de INP.

Em resumo: O Interaction to Next Paint (INP) mede quanto tempo leva para um usuário ver uma mudança visual em uma página após interagir com ela. Este INP pode ser dividido em 3 componentes: "input delay", "processing time", e "presentation delay".

O presentation delay é o principal contribuinte para o INP total, representando cerca de 42% do tempo total de INP, em média. Otimizar sua pipeline de renderização e simplificar sua estrutura HTML é a maior alavanca individual para melhorar o INP.

Presentation Delay: Já clicou em um botão e se perguntou por que demorou uma fração de segundo a mais para ver o resultado? Isso é o Interaction to Next Paint (INP) em ação. O presentation delay é a última etapa do processo de interação, entrando em ação após o seu clique ter sido processado, mas antes de você ver qualquer mudança visual.

Entendendo o presentation delay

A apresentação (presentation) é a fase final de uma interação. O presentation delay representa o tempo que o navegador leva para renderizar as atualizações visuais que seguem a interação. O presentation delay começa quando os manipuladores de eventos (event handlers) da interação terminam de rodar e termina quando o próximo quadro (contendo as mudanças visuais) é pintado (painted). O presentation delay pode ser afetado por vários fatores, incluindo a complexidade do layout, o tamanho do DOM e a quantidade de trabalho de renderização necessária.

O Interaction to Next Paint (INP) pode ser dividido em 3 subpartes: "Input Delay", "Processing Time", e "Presentation Delay".

Presentation delay e o INP

O presentation delay é a última fase do INP. Em média, o presentation delay compõe cerca de 42% do tempo total de INP, tornando-o o maior contribuinte individual para interações lentas.

No CoreDash coletamos milhões de pontos de dados de Core Web Vitals a cada hora. Com base nesses dados, o presentation delay representa 42% do Interaction to Next Paint. Isso é mais do que o processing time (40%) e significativamente mais do que o input delay (18%). Apesar de ser o maior contribuinte, o presentation delay costuma ser a fase mais difícil de otimizar porque envolve a pipeline de renderização do navegador, em vez do código da sua aplicação.

Exemplo de presentation delay: Imagine que você está no seu celular navegando em um site de e-commerce procurando um novo par de sapatos. Você toca na imagem de um produto para ver mais detalhes. No entanto, seu celular é um pouco antigo e luta para acompanhar. Você toca na imagem (Interação). O celular leva algum tempo para processar a solicitação e atualizar a tela (Processing Time). O site precisa renderizar a nova página com a imagem maior e os detalhes. Finalmente, leva um tempo perceptível para os novos detalhes do produto e a imagem aparecerem na sua tela (Presentation Delay). Esse atraso no INP pode ser frustrante para os usuários e é por isso que é importante corrigi-lo.

O que causa um alto presentation delay?

O presentation delay engloba todo o trabalho que o navegador faz depois que seus event handlers terminam e antes que os pixels apareçam na tela. Isso inclui recálculo de estilo, computação de layout, pintura (painting) e composição. Vários fatores contribuem para um alto presentation delay:

Tamanho grande do DOM

Um DOM grande ou profundamente aninhado é uma das causas mais comuns de um alto presentation delay. Toda vez que o navegador precisa atualizar o estado visual da página após uma interação, ele deve recalcular estilos, computar o layout e repintar os elementos afetados. O custo de cada uma dessas etapas escala com o número de nós do DOM que são afetados.

O Google recomenda manter seu DOM abaixo de 1.400 elementos, com uma profundidade máxima de 32 níveis e não mais do que 60 elementos filhos por nó pai (veja a auditoria de tamanho de DOM do Lighthouse). Quando o seu DOM excede esses limites, o navegador gasta muito mais tempo no recálculo de estilo e na computação de layout após cada interação.

Considere este cenário: um usuário clica em um botão que alterna uma classe CSS em um elemento de contêiner. Se esse contêiner tiver 5.000 nós descendentes, o navegador deve recalcular os estilos para potencialmente todos eles, mesmo que apenas alguns elementos mudem visualmente. Esse recálculo de estilo acontece de forma síncrona antes da próxima pintura, aumentando diretamente o presentation delay.

Para técnicas específicas para reduzir seu DOM, leia nosso guia sobre corrigir tamanho excessivo do DOM.

Trabalho de layout excessivo

Layout (também chamado de "reflow") é o processo onde o navegador calcula a posição e as dimensões de cada elemento visível na página. Após uma interação que modifica o DOM ou altera propriedades CSS que afetam a geometria (width, height, margin, padding, top, left), o navegador deve realizar o layout antes de poder pintar o quadro atualizado.

Dois padrões são particularmente prejudiciais para o presentation delay:

Layout síncrono forçado (Forced synchronous layout) ocorre quando o JavaScript lê uma propriedade de layout (como offsetHeight ou getBoundingClientRect()) após fazer uma alteração no DOM que invalida o layout. O navegador é forçado a realizar o layout de forma síncrona, dentro do seu event handler, para retornar um valor preciso. Esse trabalho de layout torna-se então parte do processing time, mas qualquer layout subsequente acionado por novas alterações no DOM torna-se parte do presentation delay.

Layout thrashing é o padrão repetido de escrever no DOM e depois ler propriedades de layout em um loop. Cada leitura força o navegador a recalcular o layout, e cada escrita invalida o layout novamente. Isso pode causar dezenas ou até centenas de cálculos de layout desnecessários por interação. Aqui está um exemplo de layout thrashing e como corrigi-lo:

\/\/ RUIM: Layout thrashing dentro de um loop
function resizeItems() {
  const items = document.querySelectorAll('.item');
  items.forEach(item => {
    \/\/ Leitura (força o layout)
    const parentWidth = item.parentElement.offsetWidth;
    \/\/ Escrita (invalida o layout)
    item.style.width = parentWidth + 'px';
  });
}

\/\/ BOM: Leituras em lote, depois escritas em lote
function resizeItems() {
  const items = document.querySelectorAll('.item');
  \/\/ Lê todos os valores primeiro
  const widths = Array.from(items).map(
    item => item.parentElement.offsetWidth
  );
  \/\/ Depois escreve todos os valores
  items.forEach((item, i) => {
    item.style.width = widths[i] + 'px';
  });
}

Renderização no lado do cliente em Single Page Applications (SPAs)

A renderização de HTML no lado do cliente pode impactar significativamente o presentation delay, particularmente em Single Page Applications (SPAs). Quando uma interação do usuário aciona uma mudança de rota ou uma grande atualização de UI, o framework SPA deve:

  1. Rodar o algoritmo de diffing do DOM virtual para determinar o que mudou
  2. Aplicar as mutações de DOM resultantes ao DOM real
  3. Acionar o recálculo de estilo e o layout para todos os elementos afetados
  4. Pintar o quadro atualizado

Em aplicações React, o processo de reconciliação do DOM virtual faz parte do processing time, mas as mutações de DOM resultantes e seu custo de renderização caem no presentation delay. Quanto mais nós de DOM sua árvore de componentes produz, mais cara é a reconciliação e o trabalho de renderização subsequente.

Para mitigar isso em aplicações React e Next.js:

  • Use React.memo() para evitar re-renderizações desnecessárias de componentes filhos que recebem as mesmas props.
  • Use useDeferredValue() para valores que acionam re-renderizações caras, permitindo que o React priorize atualizações mais urgentes.
  • Mantenha as árvores de componentes rasas. Hierarquias de componentes profundamente aninhadas produzem um DOM profundamente aninhado, o que aumenta o custo tanto da reconciliação quanto da renderização do navegador.
  • Use bibliotecas de virtualização (como react-window ou @tanstack/react-virtual) para listas longas, para que o DOM contenha apenas os itens visíveis.

Reduzindo o presentation delay

Minimize o tamanho do DOM

A maior vitória para o presentation delay é manter seu DOM pequeno:

  • Remova elementos HTML não utilizados, especialmente divs de contêiner profundamente aninhadas.
  • Use virtualização de lista para listas longas (renderize apenas os itens visíveis mais um pequeno buffer).
  • Achate estruturas profundamente aninhadas onde for possível.
  • Use CSS Grid e Flexbox em vez de divs aninhadas para o layout.
\/\/ Virtualize listas longas para reduzir o tamanho do DOM
\/\/ Antes: 10.000 itens no DOM

<ul>
  {allItems.map(item => 
     <li key="{item.id}">{item.name}<\/li>)
   }
<\/ul>

\/\/ Depois: apenas itens visíveis no DOM (usando react-window)
import { FixedSizeList } from 'react-window';

<FixedSizeList height={600} 
               itemCount={allItems.length} 
               itemSize={50} width="100%">  
  {({ index, style }) => (
    <div style={style}>{allItems[index].name}<\/div>
  )}
<\/FixedSizeList>

Use content-visibility para renderização lenta de conteúdo fora da tela

A propriedade CSS content-visibility diz ao navegador para pular a renderização de conteúdo fora da tela até que o usuário role para perto dele. Isso reduz a quantidade de trabalho de renderização durante as interações, limitando o escopo do recálculo de estilo e do layout à porção visível da página.

\/* Aplique content-visibility a seções abaixo da dobra *\/
.below-fold-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px;
}

\/* Aplique a itens individuais em listas longas *\/
.list-item {
  content-visibility: auto;
  contain-intrinsic-size: auto 80px;
}

A propriedade contain-intrinsic-size fornece uma altura estimada para que o navegador possa calcular o tamanho da barra de rolagem corretamente sem renderizar o conteúdo. Isso evita desvios de layout quando o usuário rola e o conteúdo se torna visível.

Para mais estratégias de otimização de CSS que reduzem o custo de renderização, veja o nosso guia sobre remover CSS não utilizado.

Minimize o trabalho de layout acionado por interações

Ao projetar interações, prefira propriedades CSS que não acionem layout. Propriedades como transform e opacity podem ser tratadas pelo compositor da GPU sem acionar layout ou pintura (paint). Em vez de animar top, left, width, ou height, use transform: translate() e transform: scale(). Para a lista completa de propriedades CSS que acionam layout, veja o guia de performance de renderização do web.dev.

Use a propriedade CSS will-change para dar uma dica ao navegador de que um elemento será animado. Isso permite que o navegador crie uma camada de compositor separada para o elemento, isolando sua renderização do resto da página:

\/* Promova elementos para sua própria camada de compositor *\/
.animated-element {
  will-change: transform, opacity;
}

\/* Alterne a visibilidade com opacity em vez de display *\/
.modal {
  opacity: 0;
  pointer-events: none;
  transform: translateY(10px);
  transition: opacity 0.2s, transform 0.2s;
}

.modal.active {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

Identificando longos presentation delays

Para identificar longos presentation delays, você pode usar o perfilador de performance do Chrome. Abra o DevTools (Ctrl+Shift+I), navegue até a aba Performance, clique em gravar e interaja com a página.

Você pode então analisar a linha do tempo de uma interação e visualizar as diferentes fases, incluindo o presentation delay. Ao examinar as atualizações de renderização que ocorrem após o término dos event handlers, você pode identificar quaisquer gargalos que contribuam para um longo presentation delay. Procure por entradas grandes de "Recalculate Style", "Layout", e "Paint" na linha do tempo. Estas representam o trabalho que o navegador faz durante a fase de presentation delay.

Identificando o presentation delay com dados de RUM

O Real User Monitoring (RUM) fornece atualizações em tempo real sobre métricas importantes relacionadas aos Core Web Vitals, como o Interaction to Next Paint e suas subpartes, incluindo o presentation delay. Uma ferramenta de RUM como o CoreDash divide cada interação de INP em suas três fases, permitindo que você veja se o presentation delay é o gargalo para suas páginas e segmentos de usuários específicos.

Medindo o presentation delay com Long Animation Frames (LoAF)

A API Long Animation Frames (LoAF) mostra exatamente o que causa atrasos na renderização durante as interações do usuário. A API fornece dados de tempo para separar o processing time do presentation delay e identificar quais scripts retardam a renderização.

As principais propriedades do LoAF para entender o presentation delay são:

  • renderStart: quando o navegador iniciou a fase de renderização (recálculo de estilo, layout, pintura)
  • styleAndLayoutStart: quando a computação de estilo e layout começou
  • duration: duração total do quadro de animação longo
  • blockingDuration: quanto do quadro foi bloqueado por scripts

O LoAF está atualmente disponível apenas no Chromium (Chrome 123+). Para outros navegadores, use os rastros do painel Performance do Chrome DevTools para analisar o trabalho de renderização.

A diferença entre o fim da execução do script e o fim do quadro representa o custo de renderização puro, que é o presentation delay. Aqui está como observar e registrar esses dados:

\/\/ Medir o presentation delay usando a API LoAF
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.duration > 50) {
      const scriptEnd = Math.max(
        ...entry.scripts.map(s => s.startTime + s.duration)
      );
      const presentationDelay = (
        entry.startTime + entry.duration
      ) - Math.max(scriptEnd, entry.renderStart);

      console.log('Presentation delay breakdown:', {
        totalDuration: entry.duration,
        renderStart: entry.renderStart,
        styleAndLayoutStart: entry.styleAndLayoutStart,
        estimatedPresentationDelay: presentationDelay,
        scriptCount: entry.scripts.length
      });
    }
  }
});

observer.observe({
  type: 'long-animation-frame',
  buffered: true
});

Ferramentas de RUM como o CoreDash integram dados de LoAF e mostram quais scripts e alterações de DOM causam atrasos na renderização, com atribuição completa de scripts.

Explore as outras fases do INP

Para colocar seu INP sob controle, aborde também as outras duas fases:

  • Input Delay: Minimize o tempo de espera antes que os manipuladores de eventos comecem a ser executados. O input delay é tipicamente a menor fase, mas apresenta picos durante a inicialização da página, quando a thread principal está ocupada.
  • Processing Time: Otimize o código do event handler que roda durante a interação. Na maioria das páginas, é aqui que a maior parte do seu esforço de otimização compensa.

Para um fluxo de trabalho de diagnóstico completo, veja o nosso guia sobre como encontrar e corrigir problemas de INP. Para estratégias adicionais de otimização de renderização, explore nossos guias sobre corrigir tamanho excessivo do DOM e remover CSS não utilizado. Retorne à página principal do INP para a visão geral completa.

Your Lighthouse score is not the full picture.

Lab tests run on fast hardware with a stable connection. I analyze what your actual visitors experience on real devices and real networks.

Analyze Field Data
INP Presentation Delay: Tamanho do DOM, trabalho de layout e otimização de renderizaçãoCore Web Vitals INP Presentation Delay: Tamanho do DOM, trabalho de layout e otimização de renderização