Imagem post: Tenha o DOM
Artigos

Tenha o DOM

Entenda o que é o Document Object Model e tenha o DOM.

Por
21

Muito ja foi falado sobre DOM e posso estar sendo repetitivo aqui, mas é importante falar deste assunto que em dias de manipulação pesada de seletores, percebo que pouca atenção é dada. Temos muita literatura boa sobre o assunto mas muitas vezes o foco acaba sendo o novo plugin que saiu e faz mais-do-mesmo-no-front-end-só-que-mais-fácil (E se você tiver sorte ele é free).

Entender realmente como um navegador funciona é importante, e garante seu entendimento do real dos problemas que está enfrentando no código que está implementando. Tem mais! Criar um código que manipula o layout (leia-se DOM) fica mais fácil, é uma relação win-win.

Criado pelo W3C, O DOM é uma multi-plataforma que representa como as marcações em HTML, XHTML e XML são organizadas e lidas pelo navegador que você usa. Uma vez indexadas, estas marcações se transformam em elementos de uma árvore que você pode manipular via API – que é o que fazemos quando usamos programas ou scripts para alterar funcionalidades de uma página: conteudo, estrutura ou folha de estilo.

Um pouco de história

Não tem graça falar sobre o assunto sem mostrar como ele surgiu. Isso só reforça ainda mais a importância de conhecermos bem o assunto pois mostra sua relevância (e porque falar de browser wars é bem legal, apesar de evidenciar os cabelos brancos).

Netscape e Microsoft guerreavam com Netscape 2 e IE3.0 lá em 1996 e enquanto a Netscape lançava o Javascript a Microsoft lançava o JScript. A diferença entre um e outro não é nada mais além do nome – acredite! Por razões comerciais devido as “sangrentas” browser wars as empresas decidiram adotar nomes diferentes para a mesma coisa – que na verdade era (e continua sendo) o ECMAScript, a linguagem que comecou a ser criada em 1994 quando o W3C colocou na mesma mesa as duas empresas e várias outras para desenvolver um padrão para linguagens de script para os navegadores. Javascript, JScript e ActionScript não são nada mais que dialetos de ECMAScript.

O DOM em sua forma e como é reconhecido pelos navegadores

Representação de um documento HTML e sua árvore DOM

A figura acima mostra a estrutura de uma árvore DOM, a linearização  das marcações de modo que ela possa ser montada inicialmente por um navegador. Esta estrutura não será o que veremos no navegador – o layout em si. O DOM é a base para uma outra árvore que é o que realmente um browser monta na tela, a Árvore de Renderização - aka Render Tree.

A base para todos os nós da árvore DOM é o base class chamado Node.h. Ele possui várias categorias, e as relevantes para renderizarmos código no navegador são os nós de documentos, elementos e texto.

  1. Documentos é o nó mais importante do DOM, com três classes diferentes: Document, que é usado por todos os documentos XML e outros que não sejam SVG (que também é um XML, porém com marcação já padronizada), HTMLDocument que como o nome diz, cuida de documentos HTML e SVGDocument, responsável pelos documentos SVG e tambem por outros documentos herdados da classe Document (Como o Document.h e o HTMLDocument.h).
  2. Elementos são todas as tags que estão em arquivos HTML ou XML se transformam em elementos da árvore DOM. Considerando a renderização do navegador, um elemento é um nó com uma tag que pode ser usada para fazer subclasses específicas que podem ser processadas de acordo com as necessidades da Render Tree (Element.h).
  3. Texto: É o texto que vai entre os elementos. Todo o conteúdo das tags (<p>Isto é um text node</p>). O nó de Texto guarda basicamente texto puro, que pode ser renderizado ou trabalhado via script.

A Render Tree

Como a render tree e montada

Como a render tree é montada

A Render Tree é a parte mais importante do processo de renderização. Bem parecida com a árvore DOM, cada objeto corresponde a nós de Documentos, Elementos ou Texto. A diferença é que q Render Tree possui tambem objetos que não possuem nós na árvore DOM, como scripts e folhas de estilos.

O processo de criação da Render Tree passa pelos seguintes passos:

  1. Attachment: Após finalizar o parse do DOM e a criação de seus nós, os navegadores chamam um método chamado attach para começar a renderização. O attach adiciona primeiramente as folhas de estilo a árvore DOM e começa a estilização da página. Um bom exemplo é o uso das propriedades CSS display x visibility: Caso um elemento da árvore DOM tenha uma propriedade display:none, este elemento (e seus nós filhos) não será criado na Render Tree. Ao contrário do uso de visibility:hidden, que vai renderizar o elemento na árvore, porém  ele irá remover (ou adicionar quando visibility:visible) via Repaint as cores (ou propriedades) que formam este elemento. Vale lembrar também que este processo de attach é top down, criando sempre inicialmente os nós parent e depois seus descendentes (nós filhos). (Para saber mais sobre Repaint e Reflows, veja este outro artigo)
  2. RenderStyle.h: Durante o processo de attach um método é criado, o RenderStyle.h que vai guardar objetos de referência com cada uma das propriedades CSS do documento. O nó criado no DOM é verificado no documento de CSS e caso existam propriedades que incidam naquele elemento, ela é aplicada. Esta propriedade fica salva dentro da Render Tree até que ela seja destruída ou que este valor seja alterado por algum script.
  3. CSS Box Model: Após o método RenderStyle ser criado, ele é acessado via RenderObject. O Box model é usado para posicionar um elemento dentro da página, oferecendo suporte para o conteúdo, padding, bordas e margens que envolvem este elemento

Uma representação visual do CSS box model

Destruindo (ou atualizando) a Render Tree

A Render Tree é destruída quando nós da árvore DOM são removidos, causando a necessidade de um novo parse no DOM, ou quando uma tab do navegador com a árvore DOM usada é fechada. Após o refresh da árvore DOM, todo o processo acima é refeito, com attach chamando o RenderStyle, que montado chama o método style() do RenderObject que acessa o CSS BOX model.

Como os navegadores interpretam todos estes elementos criados por DOM e Render Tree antes de aplicar o estilo?

Todo navegador tem uma lista de elementos HTML suportados. Quando o seu markup possui tags presentes na lista, a árvore DOM é montada e o processo de attachment começa logo na sequência e os estilos são aplicados, dando continuidade a criação da Render tree.

O grande problema é que cada navegador tem a sua própria lista, que trata situações similares de maneiras diferentes. Obviamente já sabemos que o navegador que mais apresenta problemas para as situações acima é o Internet Explorer, mas acredite, todos os navegadores apresentam problemas quando um elemento não está em sua lista de elementos permitidos, e precisa de um trabalho para fazer tudo acontecer na Render Tree como deve ser feito.

Elementos fora desta lista são tratados como Elementos desconhecidos. E eles são uma grande fonte de problemas:

  1. Como estilizar este elemento?Por exemplo, a tag <p> tem por padrão espacamento no topo e bottom, <blockquote> possui uma indentação automática adicionando uma margem à esquerda ou <h1> tem uma fonte maior que o <p> por ser um cabeçalho. Tudo isso esta padronizado, mas como cuidar de algo que não existe?
  2. Como este elemento deve aparecer na árvore DOM?Os navegadores também possuem uma lista que mostra quais elementos podem ser filhos de outros elementos. Por exemplo, se você adiciona por engano no seu markup <p><p> o segundo paragrafo implicitamente fechará o primeiro <p>, fazendo que os dois elementos sejam irmãos (no mesmo nível na árvore DOM) e nao como nós filhos como de maneira linear pode parecer. Porém se vc adiciona um <p><span>, este paragrafo inicial não será fechado, porque o navegador permite que <span> seja filho de elementos de paragrafo, fazendo assim o <span> ser nó filho de <p>

Para elementos desconhecidos, a ideia é não estilizar. Caso queira algum estilo em elementos desconhecidos, você deve colocá-lo no nó acima (se necessário um wrapper), para fazer com que ele herde o estilo.

Perceba a sutileza de como isso funciona. Os dois diagramas mostram uma árvore DOM, montada por um navegador suporte HTML5 nativo e o Internet Explorer 8 (navegadores que não suportam HTML5 tem funcionamento semelhante):

Arvore DOM com suporte HTML5

Arvore DOM com suporte HTML5

Arvore DOM IE e outros navegadores sem suporte HTML5

Arvore DOM IE e outros navegadores sem suporte HTML5

É por essas e outras que a gente usa o modernizr, o HTML5shiv ou um simples document.create(“SECTION”) / document.create(“ARTICLE”). E é isso que acontece quando navegadores interpretam elementos desconhecidos. Eles desconsideram o nó real aonde o elemento está, e o reconhece como filho de <BODY>. E por favor, sem trocadilhos com o filho dos outros.

Ver como uma árvore DOM é montada  e como a Render tree é feita nos dá idéia do quão importante é ter um documento semântico. Realmente semântico. Uma vez entendidos os conceitos, a manipulação e a programação dos elementos fica mais fácil.

E você começa a entender como os navegadores funcionam.

Referências

Entendendo os Reflows por Alysson Franklin

Modernizr para suporte HTML5

HTML5shiv para suporte HTML5

Browser Wars pela Wikipedia

ECMAScript pela Wikipedia

Javascript pela Wikipedia

JScript pela Wikipedia

CSS Box model pelo W3C

DOM pela wikipedia 

Renderização no webkit, o básico pela webkit

W3C Overview do DOM

Declaração de atividades do DOM pelo W3C

Uma discussão sobre como Navegadores entendem elementos desconhecidos por Mark Pilgrim  

Traversing the DOM by Mike West

Progressive enhancement demystified by Aaron Gustafson

DOM, HTML5, CSS3 e PerformanceSlides por Paul Irish

E também o @mariocaixa, esse cara tem o DOM!
21

Por Alysson Franklin

Alysson Franklin é desenvolvedor web por diversão. Lá de BH ele viu a internet nascer no Brasil, o IE vencer a guerra com a Netscape, os CD-ROMs da AOL, os pop-ups tirarem usuários do sério, o maketing "de ponta" dos banners e o nascimento dos heat maps, as newsletters virarem o precursor do spam, o javascript ser declarado como tecnologia para cybercriminosos e depois como Tábua de Salvação. Estudou Eletrônica Industrial e descobriu que pra se formar, tinha que “fazer um projeto de site para a internet”. 13 anos depois, atua como Front-End Engineer na IBM Brasil garantindo a aplicação dos padrões web, usabilidade e acessibilidade em projetos de grande porte.

http://twitter.com/alyssonfranklin

Mais posts do autor

  • Marlon

    Com certeza irei ler, obrigado!

  • Pingback: Entendendo os Reflows | Tableless - Desenvolvimento com Padrões Web

  • Rafael Martins

    HAhahahahahahahaha…

    muito criativo o título desse post.

    Nem vou falar da qualidade no conteúdo, pois aqui é 99% inquestionável.

  • Rafael Martins

    HAhahahahahahahaha…

    muito criativo o título desse post.

    Nem vou falar da qualidade no conteúdo, pois aqui é 99% inquestionável.

  • http://anestesya.posterous.com tadeu l. p. gaudio

    Cara, ficou show seu artigo, especialmente por ir mais afundo e mostrar as classes e métodos utilizados na criação da árvore do DOM.

    Achei muito interessante a parte que diz respeito ao renderizar elementos com display:none e visibility.

    Os sistemas de busca do Google tratam algumas coisas como spam se for usada a regra de display:none para um nó(muito usado na técnica de text replacement). Veja esse link que discute esse assunto: http://www.456bereastreet.com/archive/200510/google_seo_and_using_css_to_hide_text/

    Eu também já tinha lido que em SEO esconder um nó com display:none faz com que perca o SEO daquele elemnto.

    O que eu uso para fugir desse “mau uso do display:none” é usar uma position:absolute e tirar esse elemento do fluxo da tela, assim eu escondo o elemento da visualização humana, e mantenho a visualização da máquina.

    Outra ponto que achei interessante no artigo é o caso dos elementos do HTML5 que não estão presente atualmente na lista das tags em alguns navegadores e para estilizar eles basta criar um elemento no documento.

    Parabéns muito bom esse artigo!
    abs
    meu tw: @anestesya

  • http://twitter.com/alyssonfranklin Alysson Franklin

    Obrigado! O título é uma homenagem a um radialista famoso em Belo Horizonte, o arauto da alegria para muitos que assim como eu, moram longe da terrinha. O Caixa (como é conhecido em BH) pode ser encontrado em http://twitter.com/#!/mariocaixa e no seu site, se voce escutar as narracoes de gols, vc vai entender o porque esse cara tem o DOM. ;-)
    Um abraco!

  • http://twitter.com/alyssonfranklin Alysson Franklin

    Obrigado Tadeu! Sensacional a info sobre como o gSearch considera como span textos em display:none. Irei continuar em cima destes assuntos para os proximos posts, a idéia é ajudar todo mundo a se tornar expert em browsers pra ai sim comecar a galgar voos mais altos!

    Um abraco!

  • Pingback: Entendendo o DOM (Document Object Model) - m² | blog

  • Pingback: Entenda o que é o Document Object Model e tenha o DOM. | Tableless – Desenvolvimento com Padrões Web « Theodozio

  • Pingback: Quer ser bla bla bla? | Fabricio Sites

  • Pingback: Quero ser Desenvolvedor FrontEnd | Fabricio Sites

  • Rodrigo Sol

    Prezado Alysson,

    Gostaria de entrar em contato com você por e-mail. Você poderia me informar qual é?

    []‘s

  • Michel Banagouro

    Excelente!

  • Pingback: Entendendo os Reflows | Tableless

  • Pingback: Entendendo quais APIs (realmente) fazem parte do HTML5 | Tableless

  • Pingback: Entendendo quais APIs (realmente) fazem parte do HTML5 « Lucas Pinheiro

  • Weltondepaula

    Parabens cara.. muito bem esplicado

  • Johan

    Parabéns, 4 horas da manhã e eu lendo sua matéria fiquei muito interessado! rsrs Achei legal o comentário do Tadeu referente ao display!! e quanto ao título, agora eu tenho o DOM! 

  • Soneca

    Perigosooo, Muiiito perigoso aeuhaehaeuh

  • Pingback: Entendendo quais APIs (realmente) fazem parte do HTML5

  • http://www.facebook.com/fabio.a.gomes.37 Fábio A. Gomes

    excelente material, é como foi dito, é uma relação win-win compreender o funcionamento dos elementos em um browser, parebéns pelo artigo.

Mais artigos