Reduzir o escopo e a complexidade dos cálculos de estilo

O JavaScript geralmente aciona mudanças visuais. Às vezes, essas mudanças são feitas diretamente por manipulações de estilo e, às vezes, por cálculos que resultam em mudanças visuais, como pesquisar ou classificar dados. JavaScript de longa execução ou no momento errado pode ser uma causa comum de problemas de desempenho. Por isso, você deve buscar minimizar o impacto dele sempre que possível.

Cálculo do estilo

Alterar o DOM adicionando e removendo elementos, mudando atributos, classes ou reproduzindo animações faz com que o navegador recalcule os estilos dos elementos e, em muitos casos, o layout de parte ou de toda a página. Esse processo é chamado de cálculo de estilo.

O navegador começa a calcular os estilos criando um conjunto de seletores correspondentes para determinar quais classes, pseudosseletores e IDs se aplicam a um determinado elemento. Em seguida, ele processa as regras de estilo dos seletores correspondentes e descobre quais são os estilos finais do elemento.

O papel do recálculo de estilo na latência de interação

Interaction to Next Paint (INP) é uma métrica de desempenho do tempo de execução centrada no usuário que avalia a capacidade de resposta geral de uma página em relação à entrada do usuário. Ela mede a latência de interação desde o momento em que o usuário interage com a página até que o navegador pinta o próximo frame mostrando as atualizações visuais correspondentes à interface do usuário.

Um componente significativo de uma interação é o tempo que leva para pintar o próximo frame. O trabalho de renderização feito para apresentar o próximo frame é composto por muitas partes, incluindo o cálculo de estilos de página que ocorre logo antes do layout, da pintura e da composição. Este guia se concentra nos custos de cálculo de estilo, mas reduzir qualquer parte da duração total de renderização da interação também reduz a latência total.

Reduza a complexidade dos seletores

Simplificar os seletores do CSS pode ajudar a acelerar os cálculos de estilo da página. Os seletores mais simples fazem referência a um elemento no CSS com apenas um nome de classe:

.title {
  /* styles */
}

Mas, com o crescimento do projeto, o CSS provavelmente ficará mais complexo e você poderá ter seletores como este:

.box:nth-last-child(-n+1) .title {
  /* styles */
}

Para determinar como esses estilos se aplicam à página, o navegador precisa perguntar: "este é um elemento com uma classe de title com um pai de uma classe de box que é o filho menos-nth-plus-1 do elemento pai? Descobrir como pode levar algum tempo para o navegador. Para simplificar, você pode mudar o seletor para um nome de classe mais específico:

.final-box-title {
  /* styles */
}

Esses nomes de classe de substituição podem parecer estranhos, mas simplificam muito o trabalho do navegador. Na versão anterior, por exemplo, para que o navegador soubesse que um elemento era o último do tipo, ele primeiro precisava saber tudo sobre todos os outros elementos para determinar se algum elemento que viesse depois dele poderia ser o nth-last-child. Isso pode ser muito mais caro computacionalmente do que associar um seletor a um elemento com base apenas no nome da classe.

Reduzir o número de elementos que recebem estilo

Outra consideração de desempenho, e geralmente mais importante do que a complexidade do seletor, é a quantidade de trabalho que precisa acontecer quando um elemento muda.

Em termos gerais, o custo do pior caso de cálculo do estilo dos elementos computados é o número de elementos multiplicado pela contagem do seletor, porque o navegador precisa verificar cada elemento pelo menos uma vez em cada estilo para saber se ele está correto.

Os cálculos de estilo podem segmentar alguns elementos diretamente em vez de invalidar toda a página. Em navegadores mais recentes, isso tende a não ser um problema, porque o navegador nem sempre precisa verificar todos os elementos que uma mudança pode afetar. Por outro lado, navegadores mais antigos não são necessariamente otimizados para essas tarefas. Onde possível, reduz o número de elementos invalidados.

Medir o custo do recálculo do estilo

Há algumas maneiras de medir o custo do recalculo de estilo no navegador. Cada uma delas depende se você quer medir no navegador no seu ambiente de desenvolvimento ou se quer medir quanto tempo esse processo leva para usuários reais no seu site.

Medir o custo de recálculo de estilo no Chrome DevTools

Uma maneira de medir o custo dos recálculos de estilo é usar o painel de desempenho no Chrome DevTools. Faça o seguinte para começar:

  1. Abra o DevTools.
  2. Acesse a guia Performance.
  3. Marque a caixa de seleção Estatísticas do seletor (opcional).
  4. Clique em Gravar.
  5. Interaja com a página.

Quando você parar a gravação, vai aparecer algo como a imagem abaixo:

DevTools mostrando cálculos de estilo.
Um relatório do DevTools mostrando cálculos de estilo.

A faixa na parte de cima é um Flame Chart em miniatura que também representa quadros por segundo. Quanto mais próxima a atividade estiver da parte de baixo da faixa, mais rápidos serão os frames sendo pintados pelo navegador. Se você vir o Flame Chart nivelando na parte superior com barras vermelhas acima dele, significa que há um trabalho que está causando frames de longa duração.

Aumentando o zoom em
    uma área problemática no Chrome DevTools no resumo de atividades do painel de desempenho
    preenchido no Chrome DevTools.
Frames de longa duração no resumo de atividades do DevTools.

Vale a pena analisar de perto os frames de longa duração durante uma interação, como a rolagem. Se você encontrar um bloco roxo grande, amplie a atividade e selecione qualquer trabalho com a etiqueta Recalculate Style para receber mais informações sobre o trabalho de recalculo de estilo potencialmente caro.

Conseguir os
    detalhes de cálculos de estilo de longa execução, incluindo informações importantes, como
    a quantidade de elementos afetados pelo trabalho de recalculo de estilo.
Um recálculo de estilo de longa duração que leva apenas mais de 25&nbspms no resumo do DevTools.

Clicar no evento mostra a pilha de chamadas dele. Se o trabalho de renderização foi causado por uma interação do usuário, ele chama o JavaScript que acionou a mudança de estilo. Ele também mostra o número de elementos afetados pela mudança (pouco mais de 900 elementos neste caso) e o tempo necessário para o cálculo do estilo. Você pode usar essas informações para tentar encontrar uma correção para o código.

Se você tiver marcado a caixa de seleção seletor estatísticas nas configurações do Painel de desempenho antes de fazer um trace, o painel inferior terá uma guia extra com o mesmo nome.

A tabela de estatísticas do seletor de CSS
    como aparece no painel de desempenho do Chrome DevTools. Essa tabela contém
    cabeçalhos e dados correspondentes para itens como tempo decorrido, tentativas de
    correspondência, contagem de correspondências, porcentagem de nós não correspondentes, seletores e
    a folha de estilo em que eles podem ser encontrados.
A tabela de estatísticas do seletor conforme mostrada no painel de desempenho do Chrome DevTools.

Esse painel fornece dados úteis sobre o custo relativo de cada seletor, permitindo identificar seletores de CSS caros.

Para mais informações, consulte a documentação de estatísticas do seletor de CSS.

Medir o custo do recálculo de estilo para usuários reais

Se você quer saber quanto tempo leva para o recálculo de estilo ocorrer para usuários reais do seu site, a API Long Animation Frames oferece as ferramentas necessárias para isso. Os dados dessa API foram adicionados à biblioteca JavaScript web-vitals, incluindo o tempo de recálculo de estilo.

Se você suspeitar que o atraso de apresentação de uma interação é o principal colaborador do INP de uma página, convém descobrir quanto desse tempo é gasto recalculando estilos na página. Para mais informações, leia sobre como medir o tempo de recalculo de estilo no campo.

Recursos