A mesma página pode ter uma aparência diferente quando visto em dispositivos diferentes e o objetivo deste documento é mostrar essas diferenças e como podemos 'harmonizar' essas diferenças de maneira que a página continue sendo atrativa e com um bom visual.
A primeira grande diferença é que dispositivo que está exibindo a página. Há um tempo atras a grande maioria dos dispositivos navegando na Internet eram os computadores mas atualmente a maioria são celulares. E como fazemos para que a página seja bem exibida em elementos tão diferentes. A palavra da moda hoje é 'responsividade' ( auto-adaptação dos elementos a mídia de exibição ) e muitos frameworks, como o bootstrap, fazem isso com elegância e leveza.
Mas será se são compatíveis com todos os browsers ? A resposta para essa pergunta é que a cada dia estão mais compatíveis e a grande maioria dos recursos funcionam bem, mas algumas vezes temos surpresas.
Algumas vezes alguns recursos não funcionam direito, ou então alguns trechos deixam de aparecer ou são
exibidos como se o browser não entendesse o código enviado.
Muitas vezes o problema não está no site, mas sim no navegador utilizado para acessá-lo.
Isso significa que a sua experiência na
web pode mudar de acordo com o navegador que você está usando e até mesmo de acordo com a versão do browser em questão.
O que acontece é que os cinco principais navegadores do mercado usam três motores de renderização diferentes para exibir uma página da web. A coisa é tão complicada e competitiva que no browser Microsoft Edge da Microsoft ela desistiu de fazer seu próprio motor ( graças a Deus ) e agora usa o motor open source da Google.
A função do motor de renderização, também conhecido como motor de layout, é renderizar, ou seja, exibir os conteúdos solicitados na tela do navegador.
Note que a maneira mais simples de exibir uma página web seria compor uma imagem na origem e transmitir ela para o destino. Contudo isso demandaria um tráfego na rede muito grande. Para diminuir esse tráfego usamos browsers que são capazes de colocar um conteúdo de acordo com 'preceitos' definidos no motor do browser. Se você é um cara de infra deve conhecer os padrões PCL6 usados nas impressoras ou o OpenGl onde enviamos um texto junto com seu formato e o dispositivo monta a imagem da página inteira na sua memória para depois imprimir.
Portanto o mecanismo do browser é necessário para reduzir tráfego de rede, pois uma página da web não é uma entidade única que pode ser baixada e exibida na tela um pixel de cada vez. Em vez disso, ela é composta por uma série de instruções escritas em vários tipos de código – HTML, CSS, JavaScript, PHP, entre outras – que dizem ao navegador o que fazer, onde fazer e como fazer.
Cada navegador utiliza um motor de renderização para levar as informações de conteúdo e layout contidas nesses códigos e, em seguida, exibi-las totalmente formatadas e compreensíveis na tela do seu computador. O grande problema é que cada navegador usa um tipo de motor diferente e as especificações de cada linguagem de programação são muito detalhadas e cada motor só pode oferecer uma única interpretação dessa especificação. Se você conhece SQL sabe das diferenças entre o sql da Oracle, Microsoft, Postre...é tudo sql, são 90% compatíveis, mas tem 10% que mata de vez em quando.
No caso do CSS (código que fornece as informações da aparência de uma página), particularmente, nenhum motor irá conseguir reproduzir exatamente os mesmos resultados de outro. Às vezes, as diferenças podem ficar por conta apenas de um pixel desalinhado aqui ou ali ou eles podem ficar com uma aparência radicalmente diferente.
As grandes empresas estão tornando a maioria dos seus motores de web browser open source de maneira que outras empresas possam usar livremente esses motores. É claro que as empresas que usam apesar de não pagar um centavo para as marcas proprietárias contribuem para o desenvolvimento da ferramenta. Como ela é 'open source' até você pode entrar no site deles e ajudar no desenvolvimento.
Atualmente, existem quatro principais motores de renderização utilizados pelos navegadores mais populares do mercado. Atualmente só 3 deles estão em uso. São eles:
• WebKit: um motor de código aberto usado pelo Safari no OS X e iOS, assim como por muitos outros navegadores em dispositivos móveis, incluindo o navegador nativo do Android. O WebKit se tornou totalmente open source em 2005, permitindo grandes evoluções e desenvolvimentos com colaboração de terceiros e como ele foi feito já pensando em tablets e celulares largou na frente na elaboração de uma ferramenta consistente para o web browser desses dispositivos.
• Blink: um motor de código aberto baseado no WebKit. Ele alimenta navegadores como o Chrome, Opera, Amazon Silk e Android WebView (o navegador que abre dentro de aplicativos). Em 2013, o Google anunciou que aposentaria o tradicional motor de renderização que utilizava no Chrome, o WebKit, e adotaria um novo, o Blink. O motor foi modificado pelo próprio Google para melhorar o desempenho e reduzir a complexidade do navegador.
• Gecko: um motor de código aberto desenvolvido pela Fundação Mozilla e usado pelo Firefox. O Gecko roda em vários sistemas operacionais tendo suporte para BSD, Linux, Mac OS X, Solaris, OS/2, AIX, OpenVMS e Windows.
• Trident: um motor desenvolvido pela Microsoft e usado no Internet Explorer. Graças a Deus, desde o Windows 10 a Microsoft no browser Microsoft Edge usa o motor da Google.
Atualmente, o descompasso entre os diferentes motores de renderização é muito menor do que era na época em que o
Internet Explorer dominava o mercado de navegadores. Suítes de testes como a Acid3 ( http://acid3.acidtests.org )
mostram com que precisão um navegador renderiza uma página e a maioria dos browsers modernos apresenta uma pontuação
alta ( 100% é o máximo ).
No entanto, manter a compatibilidade com os padrões web (Web Standards) é uma tarefa realmente complexa. Os padrões
web têm por finalidade a padronização e a criação de uma "Web universal".
As especificações para HTML, CSS e outros são enormes e estão em contínuo desenvolvimento. Novos elementos são adicionados, enquanto os mais velhos, não utilizados ou obsoletos, são removidos. Todos esses detalhes podem fazer com que os motores de renderização levem um tempo para refletir tantas alterações. Mesmo hoje alguns elementos do HTML5 e especificações CSS ainda não são suportados por alguns navegadores ou o tratamento feito do elemento é muito diferente de um para outro browser.
O site https://html5test.opensuse.org/ permite testar seu navegador, mais especificamente a versão que está sendo executada, para ver quão bem ele suporta ambos os recursos oficiais e experimentais do HTML5. Atualmente, o Chrome é classificado como o melhor dos principais navegadores do mercado.
Por default quando um navegador não entende um recurso definido pelo código da página ela simplesmente joga fora esse conteúdo. Você precisaria abrir o depurador do browser ( F12 no Chrome / Edge) e observar a informação de erro.
Note também que os recursos do browser foram ampliados e muito, de uma simples ferramenta de exibição de texto e imagens para um mecanismo que até tem codecs de vídeo embutidos fazendo com que hoje possamos incluir objetos multi-mídia, entre outros, diretamente no browser.
Além de tudo isso que citamos, ainda há outros fatores que devem ser levados em conta, como por exemplo:
• Bugs no motor: um motor de renderização é um software e todo software contém bugs. Embora as empresas geralmente encontrem e eliminem bugs críticos rapidamente, é impossível garantir que uma combinação específica de código em uma página da web não vai produzir resultados inesperados quando for processada.
• Bugs na página web: navegadores têm certo nível de tolerância à erros, mas isso varia de um motor para o outro. Uma página web com erros em seu código pode ser executada perfeitamente em um navegador, mas aparecer totalmente quebrada em outro.
• Fontes: a grande maioria dos recursos são exibidas diretamente no navegador. Contudo algumas vezes
ele pode recorrer a serviços do sistema operacional do dispositivo para implementar uma tarefa.
Um simples serviço de ftp que baixa as imagens do browser é feita em parceria com o sistema operacional e o browser.
Saber como funciona a renderização de páginas web é um item crucial para o desenvolvimento web a maioria das regras não estão explicitamente explicadas aos usuários e muitas dessas regras os desenvolvedores armazenam na sua memória como bagagem profissional mas se esquecem que podemos esquecer coisas importantes por absoluta falta de uso.
Esta página é baseada em What Every Frontend Developer Should Know About Webpage Rendering, do Frontend Babel.
Note que o processo de renderização deve ser o mais perfeito possível para renderizar a página rapidamente e com o menor
custo possível para o browser e por isso todas as técnicas de otimização são empregadas para melhorar o desempenho.
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.
Resumidamente, estas são as ações de um browser ao renderizar uma página:
• O DOM (Document Object Model) é montado a partir do código HTML recebido de um servidor.
• Os estilos são carregados e analisados (parsed), formando a CSSOM (CSS Object Model).
• Sobre DOM e CSSOM, uma árvore de renderização (rendering tree) é criada — um conjunto de objetos a serem renderizados, que podem ser chamados renderizador (renderer), objeto de renderização (render object), frame e outros, conforme a engine que se está trabalhando. Essa árvore de renderização reflete a estrutura do DOM — excetuando-se elementos invisíveis, como a tag <head> ou elementos estilizados com display: none;). Cada string de texto é representada na rendering tree como um processador separado. Cada um dos objetos de renderização contêm seu objeto correspondente no DOM (ou um bloco de texto) mais os estilos calculados. Em outras palavras, a árvore de renderização descreve a representação visual do DOM.
• Para cada elemento da árvore, suas coordenadas são calculadas — o que é chamado de “layout”. Navegadores usam um método fluido que exige somente uma “passagem” para montar o layout de todos os elementos (com exceção de tabelas, que exigem mais do que uma passagem).
• Finalmente, tudo é efetivamente exibido em uma janela do navegador, num processo chamado de “pintura” (“painting”).
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.
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).
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:
• Manipulação do DOM (adição de elemento, exclusão, alteração ou alterar na ordem dos elementos)
• Alterações de conteúdos, incluindo alterações de texto em campos do formulário
• Cálculos e/ou alterações de propriedades CSS
• Adição ou remoção de folhas de estilo
• Alteração no atributo class
• Manipulação na janela do navegador (redimensionamento, rolagem etc)
• Ativação de pseudo-classe (:hover)
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):
var $body = $('body');
// somente 1 reflow e repaint vão realmente acontecer
$body.css('padding', '1px'); // reflow, repaint
$body.css('color', 'red'); // repaint
$body.css('margin', '2px'); // reflow, repaint
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:
var $body = $('body');
$body.css('padding', '1px');
$body.css('padding'); // leitura de propriedade força um reflow
$body.css('color', 'red');
$body.css('margin', '2px');
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:
.has-transition {
-webkit-transition: margin-left 1s ease-out;
-moz-transition: margin-left 1s ease-out;
-o-transition: margin-left 1s ease-out;
transition: margin-left 1s ease-out;
}
Procedendo com a implementação:
JavaScript
// elemento tem a classe "has-transition" por padrão
var $targetElem = $('#targetElemId');
// remove a classe de transição
$targetElem.removeClass('has-transition');
// altera a propriedade esperando acabar com a transição,
// já que a classe não está mais ali
$targetElem.css('margin-left', 100);
// coloca a classe de transição novamente
$targetElem.addClass('has-transition');
// altera a propriedade
$targetElem.css('margin-left', 50);
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:
// remove a classe de transição
$(this).removeClass('has-transition');
// altera a propriedade
$(this).css('margin-left', 100);
// força o reflow para as mudanças serem aplicadas imediatamente
$(this)[0].offsetHeight; // só um exemplo; também funcionaria com outras propriedades
// coloca a classe de transição de volta
$(this).addClass('has-transition');
// altera a propriedade
$(this).css('margin-left', 50);
Agora funciona como o esperado!
Em resumo, pode-se aconselhar o seguinte:
• Crie HTML e CSS válidos, não se esqueça de especificar a codificação do documento. Regra geral, estilos devem ser incluídos em <head> e scripts externos ao final da tag <body>.
• Simplifique e otimize seletores CSS segundo algumas dicas já mostradas por aqui (essa otimização é quase universalmente ignorada por desenvolvedores que usam pré-processadores CSS).
• Nos scripts, minimize a manipulação do DOM sempre que possível. Faça cache de tudo, incluindo propriedades e objetos (caso estes sejam reutilizados no decorrer do código). É melhor trabalhar com um elemento “offline” ao realizar manipulações complicadas — um elemento “offline” é aquele que está desligado da DOM e só em memória — e anexá-lo ao DOM depois.
• Se você usa jQuery, siga as melhores práticas para seletores jQuery.
• Para alterar os estilos de um elemento, modificar o atributo “class” é uma das maneiras mais performáticas; quanto mais fundo na árvore do DOM for essa mudança, melhor (também pelo fato de que isso ajuda a separar a lógica de apresentação).
• É uma boa ideia desativar animações complexas em :hovers durante a rolagem de tela (por exemplo, adicionando uma classe extra “no-hover” a <body> ).
O trabalho de 'customizar' um elemento de acordo com a 'janela de exibição' é em muito facilitado quando usamos frameworks feitos para isso. Digamos que é uma ferramenta pronta para ser utilizada e você não precisa quebrar a cabeça..tá pronta...é só usar. E, normalmente, esses 'frameworks' são pequenos, menores de 50 KB.
A regra para que sites responsivos funcionem é que o browser sabe as dimensões da janela do browser e num 'repaint' ( por exemplo, quando você redimensiona a tela ) ao renderizar novamente os elementos da página ele dispara eventos que podem tomar atitudes e dimensionar os elementos da página aplicando, por exemplo, uma classe ( ou css ) de acordo com a dimensão da tela.
Fazer um site responsivo dá muito mais trabalho porque você precisa redimensionar cada item e ver como ele fica em relação aos demais. Você precisa aplicar o redimensionamento em cada elemento da página e não na página inteira como a princípio pareceria o mais correto.
O bom do Bootstrap é que ele é mobile-first, ou seja, dá prioridade a exibição em dispositivos móveis
( que são os mais difíceis porque tem um hardware simplificado e pobre) e depois em dispositivos não móveis.
Como a maioria dos dispositivos na Internet hoje são celulares é 'saudável' contar com o bootstrap.
O bootstrap está ligado diretamente aos eventos do browser e por isso no browser temos as definições de breakpoints, ou seja, definição de um limite que quando a janela ultrapassar esse limite dispara um evento que pode ser 'trapeado' pelo bootstrap e com isto ele pode redimensionar os elementos da página. Os breakpoints definidos no Bootstrap são:
Breakpoint | Sigla da Classe | Dimensões (pixels) |
Extra-Pequeno ( X-Small ) | Nenhuma | menor que 576 |
Pequeno ( Small ) | sm | maior ou igual a 576 |
Médio ( Medium ) | md | maior ou igual a 768 |
Grande ( Large ) | lg | maior ou igual a 992 |
Extra grande ( Extra Large ) | xl | maior ou igual a 1200 |
Extra-Extra grande ( Extra extra Large ) | xxl | Maior ou igual a 1400 |
Você deve estar se perguntando...pra que tantos 'breakpoints' no browser ? Esses breakpoint foram definidos
desde a era pré-histórica dos celulares até os dispositivos mais modernos.
Hoje temos tablets com mais definição de tela que muitos computadores antigos.
Outra coisa que você precisa pensar é que a mesma página pode ser exibida num PSP, GameBoi ou coisa parecida e
também pode ser exibida num monitor ultra-wide-screen de um nerd genial. Faz parte né ?
Eu jamais na minha vida vou achar um design 'agradável' ao abrir uma página e esta deixa um monte de espaço em branco especialmente nas laterais. Parece um 'cabresto' para jegues nerds.
Vou fazer uma espécie de 'cabeçalho' de uma página...com 2 imagens na lateral e 1 texto ao centro. Bem simples mas basicamente é o que precisamos para um cabeçalho de página
Abaixo é como ele ficaria sem o bootstrap:
Este seria um texto qualquer.
Reduza a largura da tela e veja como fica. Os 3 elementos são exibidos na mesma linha quando cabem nela. Quando não cabe, o elemento mais a direita é deslocado para a linha abaixo. Quando a janela fica muito pequena o próprio browser reduz as dimensões da imagem. Sem bootstrap é o que daria para fazer...fica realmente muito ruim.
Código:
<img src="../imagens/apple-gear-looking-pretty.jpg" style="width:30%" />
<span style="font-size:33px;">Este seria um texto qualquer.</span>
<img src="../imagens/ArcodoTriunfo.jpg" style="width:30%"/>
Se você está estudando html com esta página vá aplicando as medias queries da largura maior para a menor de acordo com o andamento da página. Se você aplicar todas as medias queries de uma vez não vai entender qual foi o critério que usei para fazer o código.
Agora faremos a exibição dos mesmos elementos usando as media-queries do bootstrap para redimensionar os elementos ao tamanho da tela. Note que a coisa é simplificada porque são só 3 elementos...se fossem 10 seria um caos. Veja como que fica.
Este seria um texto qualquer.
Agora reduza a largura da tela do browser para ver o que acontece. Para facilitar, abaixo coloquei um script que exibe a largura da tela do browser
A largura da tela do browser no momento é de (pixels): 0
Comecei primeiramente pela tela maior:
@media (min-width: 1400px) {
#img1, #img2 {
width: 30%;
}
#txt1{
font-size:33px;
}
}
Traduzindo o código acima coloquei as 2 imagens ocupando cada uma 30% da largura da linha deixando os 40% restantes para o texto. Quanto ao texto defini um tamanho de 33px. Escolhi esses valores porque queria os 3 elementos na mesma linha.
A largura da tela da minha máquina é de 1488 px e isso faz com que esse estilo seja aplicado, ou seja, a media querie acima é aplicada quando a largura mínima for de 1400 px...como minha tela tem 1488 ela foi aplicada.
Nosso media querie está sendo aplicado quando a tela tiver 1400px ou mais.
Reduza a tela até a largura abaixo de 1400px. Você vai notar que o estilo não é mais aplicado e a segunda
imagem vai para a linha de baixo. Precisamos definir o segundo break...quando for menor de 1200 px.
Código:
@media (min-width: 1200px) {
#img1, #img2 {
width: 25%;
}
#txt1 {
font-size: 30px;
}
}
Nesta segunda media-querie reduzi as imagems para 25% do tamanho original e o texto de 33 px para 30px.
Nossa midia-querie está sendo aplicada quando a tela tem no mínimo 1200px. Reduza a tela para uma largura abaixo de 1200 px...novamente ocorre o mesmo problema...a media querie deixa de ser aplicada e a segunda imagem vai para a linha de baixo. Vamos definir o próximo 'breakpoint' : 992px
Código:
@media (min-width: 992px) {
#img1, #img2 {
width: 20%;
}
#txt1 {
font-size: 25px;
}
}
Na media querie com a tela maior que 992 px alterei a largura das imagens para 20% e do texto para 25%. Redimensione a tela e veja o efeito. Até 768 px ela vai funcionar bem mas em 768 px preciso definir o novo 'breakpoint'.
Código :
@media (min-width: 576px) {
#img1, #img2 {
width: 10%;
}
#txt1 {
font-size: 15px;
}
}
Na media-querie da tela maior que 576px alterei o dimensionamento das imagens para 10% e da fonte de letras para 15 px. Sei que não seria o melhor dimensionamento mas minha intenção é exibir como funciona a ferramenta e não fazer uma página para front-end.
Finalmente chegamos na última possibilidade...e se a tela for menor que 576px ? A resposta é a seguinte: você define diretamente no estilo o formato default desejado para essa dimensão. As demais dimensões definimos acima. Veja como fica o código total:
<style>
#img1, #img2 {
width: 8%;
}
#txt1 {
font-size: 10px;
}
@media (min-width: 576px) {
#img1, #img2 {
width: 10%;
}
#txt1 {
font-size: 15px;
}
}
@media (min-width: 768px) {
#img1, #img2 {
width: 15%;
}
#txt1 {
font-size: 20px;
}
}
@media (min-width: 992px) {
#img1, #img2 {
width: 20%;
}
#txt1 {
font-size: 25px;
}
}
@media (min-width: 1200px) {
#img1, #img2 {
width: 25%;
}
#txt1 {
font-size: 30px;
}
}
@media (min-width: 1400px) {
#img1, #img2 {
width: 30%;
}
#txt1{
font-size:33px;
}
}
</style>
</head>
Vai concordar comigo que deu um trabalhão mas ficou demais. Acho que dá pra exibir a página até no meu PSP.
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 — principalmente na medida em que as tecnologias web avançam e o conhecimento dessa parte teórica se torna cada vez mais vital.
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.
Importante : Considero o conteúdo desta página como 'Não Terminado' por que os conceitos aqui apresentados estão em constante evolução.