Uma das coisas mais importantes no desenvolvimento web e que todo front-end deveria saber é webpage rendering. Por isso, hoje vou falar um pouco sobre como isso funciona e mostrar alguns princípios da renderização, como repaint, reflow e como o browser otimiza esses processos.
Pretendo falar sobre os conceitos básicos, mas caso você tenha interesse em ir além, a israelita Tali Garsiel fez uma pesquisa bastante aprofundada sobre o assunto, que você pode ver nesse link: “How browsers work: Behind the scenes of modern web browsers”.
Entender como uma página é renderizada é fundamental, pois garante respostas de muitas questões sobre as melhores práticas de desenvolvimento e possibilita que os desenvolvedores tomem decisões corretas.
Cada engine dos navegadores funciona de forma diferente, e isso requer um estudo específico de cada uma delas. Mas vou listar aqui as ações mais comuns quando a página está sendo renderizada:
- DOM: a engine de renderização vai parsear o HTML localizado no servidor e transformar suas tags em nós do DOM (Document Object Model) em uma tree chamada de “content tree”;
- CSSOM: os estilos são carregados e parseados, formando o CSSOM (CSS Object Model);
- Render tree: a união entre o DOM e o CSSOM forma uma nova tree, chamada de “render tree”, que é uma série de objetos para serem renderizados. Render tree contém toda a estrutura do DOM, mas sem os elementos invisíveis (Tag <head> ou elementos que possuem display:none;). O render tree é a representação visual do DOM, ou seja, cada objeto a ser renderizado possui seu objeto do DOM correspondente aos seus atributos visuais, como cores e dimensões, e vem na ordem correta para ser exibida na tela;
- Layout (flow): o render tree é o suficiente para começar a calcular as coordenadas e posicionar os elementos na tela. Nós chamamos esse processo de “layout”. O browser utiliza o método “flow” nesse passo, somente uma vez para todos os elementos. A exceção são as tabelas, que exigem sua utilização mais de uma vez;
- Painting: Por fim, temos o processo “painting”, no qual o render tree irá passar por cada objeto e irá mostrar na tela.
Atenção: elementos com visibility: hidden; que, ao contrário do display:none;, está no render tree.
reflow/repaint
Quando a página está sendo renderizada, sabemos que o layout e o painting são executados pelo menos uma única vez (exceto se você está renderizando uma página em branco). Porém, na interação do usuário com a página os scripts podem modificar o DOM e o CSSOM e, então, alguns passos acima podem ser repetidos.
- reflow: quando algum script modifica o tamanho ou posicionamento dos elementos na página;
- repaint: quando são alterados estilos que não afetam o tamanho ou posicionamento dos elementos na página (background-color: red), somente o repaint é disparado.
Exemplos reflow/repaint
```javascript var bodyStyle = document.body.style; bodyStyle.width = "500px"; // reflow e repaint bodyStyle.padding = "10px"; // reflow e repaint bodyStyle.backgroundColor = "blue"; // repaint bodyStyle.color = "red"; // repaint bodyStyle.display = "none"; // reflow e repaint bodyStyle.visibility = "hidden"; // repaint ```
Executar um reflow ou um repaint é custoso para o browser, portanto ele evita esse processo sempre que pode, funcionando de forma inteligente.
Otimizando a renderização
Executando esse script, quantos reflows e repaints vamos ter no final?
```javascript var bodyStyle = document.body.style; bodyStyle.padding = "10px"; // reflow e repaint bodyStyle.backgroundColor = "blue"; // repaint bodyStyle.color = "red"; // repaint bodyStyle.margin = "10px"; // reflow e repaint ```
Se sua resposta foi mais de 1 vez, você está errado. Para otimizar o processo e evitar vários reflows e repaints, o browser guarda todas as instruções e executa tudo de uma só vez no final do script. Legal, não?
Você também pode forçar a execução de um reflow e repaint apenas lendo a propriedade. Veja:
```javascript var bodyStyle = document.body.style; bodyStyle.padding = "10px"; bodyStyle.padding; // reflow forçado bodyStyle.color = "red"; bodyStyle.margin = "10px"; ```
No exemplo acima, temos dois reflows sendo executados, pois forçamos sua execução quando lemos a propriedade padding
do
body
.
Sabendo disso, você deve ter notado que já temos uma boa prática caso você não queira forçar um repaint ou um reflow propositalmente.
Uma maneira melhor ainda de inserir estilos em nossos elementos e causar o mínimo de impacto para o browser é inserindo somente a classe CSS no elemento. Exemplo:
```javascript // Ruim var bodyStyle = document.body.style, padding = 10, margin = 10; bodyStyle.padding = padding + “px”; bodyStyle.margin = margin + “px”; // Melhor var body = document.body; body.className = ”alguma-classe”;
Considerações finais
Entendendo como o browser renderiza nossas páginas, podemos provar algumas boas práticas, como as abaixo:
- No seus scripts, evitem manipular o DOM sempre que possível;
- Não modifique os estilos dos elementos, use classes ao invés disso;
- Quando for criar animações, tente aplicar com os elementos em position absolute ou fixed.
Dúvidas, críticas ou sugestões? Não esqueçam de comentar abaixo.
Espero que esse artigo tenha sido útil. Divirtam-se e até a próxima!