Saber mais sobre renderização de páginas web e como isso é importante para o desenvolvimento web é crucial — e espanta o fato de 100% dos desenvolvedores front-end não aprenderem isso logo nos primeiros dias de seus estudos. Vários artigos cobrindo o assunto estão disponíveis, mas a informação é dispersa e, de certa forma, fragmentada.

A renderização tem de ser otimizada desde o início, quando o layout da página está sendo definido, e ser tão crucial quanto o papel de estilos e scripts têm na renderização de páginas. É interessantíssimo que profissionais/estudiosos da área conheçam certos truques para evitar alguns problemas de desempenho.

Como navegadores renderizam página web

Resumidamente, estas são as ações de um browser ao renderizar uma página:

Quando as pessoas interagem com a página ou os scripts a modificam, algumas das operações acima mencionadas têm de ser repetidas, tal como mudanças na estrutura subjacentes da página.

Repaint

Ao mudar estilos de elementos que não afetam a posição desse elemento na página (como background-color, border-color, visibility etc), o browser apenas “repinta” (repaint) o elemento com os novos estilos aplicados (que significa que um repaint ou restyle está acontecendo).

Reflow

Quando as alterações afetam o conteúdo ou estrutura do documento ou a posição de um elemento, um refluxo (reflow) ou relayout acontece. Essas alterações são geralmente desencadeadas por:

Como navegadores otimizam a renderização

Navegadores tentam fazer seu melhor para restringir repaint/reflow apenas para a área que abrange os elementos alterados. Por exemplo, uma mudança de tamanho em um elemento posicionado com absolute ou fixed afeta somente o próprio elemento e seus descendentes, enquanto uma mudança semelhante em um elemento static (o padrão de posicionamento em CSS) provoca reflow em todos os elementos subsequentes.

Outra técnica de otimização usada pelos browsers é que, durante a execução de trechos de código JavaScript, eles armazenam as alterações e as aplicam em uma única passada depois que o código foi executado. Por exemplo, este trecho de código só irá desencadear um reflow e repaint (amostras de código a seguir usando jQuery):

Entretanto, como mencionado acima, acessar uma propriedade de um elemento desencadeia um reflow forçado. Isso acontecerá se se acrescentar uma linha extra que lê uma propriedade do elemento do bloco anterior:

Como resultado, obtém-se 2 reflows ao invés de 1. Diante disso, fica claro que é uma boa prática agrupar e fazer leituras de propriedades de elementos em conjunto para otimizar a performance (veja um exemplo mais elucidativo no JSBin).

Há situações em que é preciso forçar um reflow. Exemplo: é preciso aplicar a mesma propriedade (margin-left, por exemplo) para o mesmo elemento duas vezes. Inicialmente, deve ser definido como 100px sem animação e, então, tem que ser animado com transição para um valor de 50px. Você pode estudar este exemplo no JSBin, mas veja a seguir alguns detalhes da implementação.

Começando por criar uma classe CSS com a transição:

Procedendo com a implementação:

Esta implementação, no entanto, não funciona como esperado. As mudanças são cacheadas e aplicados apenas no fim do bloco de código. É preciso forçar um reflow:

Agora funciona como o esperado!

Conselhos práticos sobre otimização

Em resumo, pode-se aconselhar o seguinte:

Conclusão

Como é e como se dá o processo de renderização de páginas web deveria ser algo que desenvolvedores front-end aprendem nos primeiros dias de seus estudos. Curiosamente, isso não acontece — talvez pelo fato mesmo de os conteúdos a este respeito se encontrarem dispersos e não organizados. Fato é que, com este conhecimento em mãos, é possível planejar e projetar melhor o design de seus códigos e a maneira como isso impactará na performance do site.