# Explicador de estrutura HTML e DOM

> Cole HTML e leia a árvore que o parser de HTML constrói a partir dele: cada elemento, nó de texto e comentário com a sua linha, os elementos que o parser criou sem tag (html, head, body, tbody), as tags de fechamento que ele supriu, os elementos de formatação que dividiu e o conteúdo que moveu para fora de uma tabela, com o modo do documento (quirks ou não) e cada erro de análise pelo código e posição da própria especificação. Depois, os achados: o DOCTYPE, o idioma, o título, a codificação, imagens sem texto alternativo, links e botões sem nome, saltos de título, ids duplicados, controles sem rótulo, elementos e atributos obsoletos, cada um ligado a uma frase do HTML Standard ou da WCAG 2.2. Só análise: nenhum script roda, nada é buscado, nada é renderizado.

- Tool: https://ronutz.com/pt-BR/tools/html-structure-explainer
- Family: Web e HTTP

---

## O que faz

Lê HTML (um documento inteiro ou um fragmento) com o mesmo parser que os navegadores são especificados para usar e mostra o que saiu: a árvore (cada elemento, nó de texto e comentário, recuado pela profundidade, com a linha da sua tag), os elementos que o parser criou sem tag, as tags de fechamento que ele supriu, os elementos de formatação que dividiu, o conteúdo que moveu para fora de uma tabela, o modo do documento (no-quirks, limited-quirks ou quirks), o DOCTYPE, o título, o idioma e a codificação que o documento declara, cada erro de análise pelo código da própria especificação com linha e coluna, a estrutura de títulos, e uma lista de achados sobre estrutura e acessibilidade, cada um ligado a uma frase do HTML Standard ou da WCAG 2.2. Conta também o que teria rodado e não rodou: elementos script, manipuladores de evento inline, URLs javascript:, elementos style, iframes.

O parser é o parse5, o parser de HTML conforme à especificação usado pelo jsdom, pelo Cheerio e pelo compilador do Angular, executado com posições no código e com a chamada de erros de análise ligada, e com a flag de scripting desligada (como o DOMParser analisa). Nada é executado, buscado ou renderizado. A API hospedada roda o mesmo código e devolve a mesma árvore.

## Como ler a árvore

- Um **ponto** na coluna das linhas marca um nó sem posição no código: o parser o criou. A especificação: "Omitting an element's start tag in the situations described below does not mean the element is not present; it is implied, but it is still there." html, head, body e tbody são os habituais.
- **fim suprido** marca um elemento cuja tag de fechamento não está no código. Para 19 elementos a especificação permite isso (13.1.2.4 Optional tags: html, head, body, li, dt, dd, p, rt, rp, optgroup, option, colgroup, caption, thead, tbody, tfoot, tr, td, th); para qualquer outro significa que a tag de fechamento faltou ou que outra tag o fechou antes, e o achado D13 diz qual.
- **parte n** marca o resultado do adoption agency algorithm: quando uma tag de fechamento fecha um elemento de formatação (a, b, i, em, strong, font, small, s, u, code, nobr, big, tt, strike) que não é o elemento aberto mais interno, o parser o fecha e reabre uma cópia em volta do que segue, de modo que um elemento do código vira vários (achado D14).
- **movido** marca o foster parenting: texto ou elementos escritos dentro de uma tabela onde só partes de tabela podem aparecer são inseridos antes da tabela (achado D15).
- **vazio** marca os 13 elementos que nunca têm tag de fechamento (area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr). Uma barra final neles é "unnecessary and has no effect of any kind"; em qualquer outro elemento HTML é um erro de análise e o elemento continua aberto.

## Os erros de análise

A especificação define exatamente o tratamento de erros, então um documento com erros ainda tem uma árvore exata: "Parse errors are only errors with the syntax of HTML." A sua tabela de erros nomeados (13.2.2) tem 52 códigos, cada um com uma descrição não normativa; a página cita a descrição ao lado de cada erro. Os erros da construção da árvore (uma tag de fechamento perdida, elementos abertos no fim, um segundo body) são descritos na prosa da especificação sem código; o parse5 nomeia esses por conta própria (missing-doctype, end-tag-without-matching-open-element, open-elements-left-after-eof e mais nove), e a página marca qual autoridade nomeou cada código.

## Os achados

D1 sem DOCTYPE e D2 DOCTYPE legado (quirks mode); D3 sem lang na raiz (WCAG 3.1.1); D4 título ausente, repetido ou vazio (modelo de conteúdo do head, WCAG 2.4.2); D5 declaração de codificação ausente, além dos primeiros 1024 bytes, ou não UTF-8; D6 img sem alt e D7 img com alt vazio (WCAG 1.1.1 e as regras de texto alternativo da especificação); D8 link ou botão feito só de imagens sem texto alternativo; D9 saltos de título e h1 ausente (4.3.11: "less than, equal to, or 1 greater"); D10 ids duplicados; D11 e D12 os elementos e atributos obsoletos da seção 16.2, cada um com o conselho de substituição da especificação; D13 a D16 o que o parser reparou; D17 um controle rotulável sem rótulo; D18 o que não rodou; D19 títulos vazios (WCAG 2.4.6); D20 os elementos que o parser criou.

## Limites

- O parse5 8.0.1 implementa a especificação tal como estava no seu lançamento. A tokenização de instruções de processamento que a especificação ganhou em 2026 não está nele: `<?…>` é relatado sob o nome anterior unexpected-question-mark-instead-of-tag-name e vira comentário, que é também o que a especificação atual faz com um alvo xml.
- Os achados leem estrutura, não significado: se um texto alternativo é bom, se um título descreve a sua seção, se uma etiqueta lang está certa, não são perguntas que um parser responda. headingoffset e headingreset não são aplicados à estrutura.
- A lista da árvore para em 2.000 nós (as contagens cobrem tudo); entradas acima de 200.000 caracteres são recusadas.

## Fontes

- [HTML Living Standard, 13 The HTML syntax: 13.2.2 Parse errors](https://html.spec.whatwg.org/multipage/parsing.html#parse-errors) (lido em 2026-10-05)
- [HTML Living Standard, 4.3.11 Headings and outlines](https://html.spec.whatwg.org/multipage/sections.html#headings-and-outlines) (lido em 2026-10-05)
- [HTML Living Standard, 16.2 Non-conforming features](https://html.spec.whatwg.org/multipage/obsolete.html#non-conforming-features) (lido em 2026-10-05)
- [WCAG 2.2, W3C Recommendation 12 December 2024](https://www.w3.org/TR/WCAG22/) (lido em 2026-10-05)
- [parse5](https://github.com/inikulin/parse5) (lido em 2026-10-05)

## Standards and references

- [HTML Living Standard (WHATWG): 13 The HTML syntax, 13.2.2 Parse errors, 13.2.6 Tree construction](https://html.spec.whatwg.org/multipage/parsing.html#parse-errors) - void, raw text and escapable raw text elements; optional tags; the trailing solidus; the 52 named parse errors and their non-normative descriptions; implied end tags; the initial insertion mode and quirks mode
- [HTML Living Standard (WHATWG): 3.2.6 Global attributes (id), 4.1.1 html (lang), 4.2 Document metadata (head, title, meta charset), 4.3.11 Headings and outlines, 4.8.4.4 Alternative text for images, 4.10.4 label](https://html.spec.whatwg.org/multipage/sections.html#headings-and-outlines) - id uniqueness; lang encouraged on the root; exactly one title; the encoding declaration within 1024 bytes; heading levels less than, equal to, or one greater than the previous; alt must be specified, empty for decorative images; links and buttons made of images; labelable elements
- [HTML Living Standard (WHATWG): 16.2 Non-conforming features](https://html.spec.whatwg.org/multipage/obsolete.html#non-conforming-features) - the 29 elements that are entirely obsolete and must not be used by authors, and the obsolete attributes, each with the standard's replacement advice
- [Web Content Accessibility Guidelines (WCAG) 2.2, W3C Recommendation 12 December 2024](https://www.w3.org/TR/WCAG22/) - SC 1.1.1 Non-text Content, 1.3.1 Info and Relationships, 2.4.2 Page Titled, 2.4.6 Headings and Labels, 3.1.1 Language of Page; 4.1.1 Parsing obsolete and removed
- [parse5 8.0.1, the HTML parser (MIT), with its parse-error codes](https://github.com/inikulin/parse5) - parse() with sourceCodeLocationInfo and onParseError; the default tree adapter; the 60 error codes (48 of the standard's, 12 named by parse5)

## Related reading

- [Como o parser de HTML repara a sua marcação, e por que os reparos são iguais em todos os navegadores](https://ronutz.com/pt-BR/learn/how-the-html-parser-repairs-your-markup.md): Um navegador nunca rejeita HTML. Seja o que for que você cole, uma árvore sai, e o HTML Standard diz exatamente qual árvore: os elementos que o parser cria por você, as tags de fechamento que ele supre, os elementos de formatação que divide, o conteúdo que tira de dentro das tabelas, os comentários que faz dos seus erros de digitação, e o quirks mode em que cai sem um DOCTYPE. Os 52 erros de análise nomeados, os cinco reparos que vale conhecer pelo nome, em que view source e inspecionar elemento discordam, e por que a WCAG 2.2 pôde abandonar o seu critério de análise sem baixar a régua.
- [Como um seletor encontra os seus elementos: o Selectors Level 4 lido como um algoritmo de casamento](https://ronutz.com/pt-BR/learn/how-a-selector-finds-its-elements.md): Um seletor CSS é uma pergunta feita a uma árvore, e a especificação diz exatamente como a pergunta é respondida: composto por composto, da direita para a esquerda, com a linguagem do documento decidindo o que conta como o mesmo nome. Onde a caixa importa e onde não importa, os sete operadores de atributo e a string vazia que não casa com nada, como os irmãos são contados, o que :is(), :not(), :where() e :has() fazem com a validade e a especificidade, que pseudoclasses um documento estático nunca pode responder, e o que os navegadores fazem com um seletor que termina dentro de um colchete.
- [O que o head de uma página declara, e quem lê cada linha](https://ronutz.com/pt-BR/learn/what-a-page-head-declares-and-who-reads-it.md): O head de uma página HTML é escrito para máquinas, e cada linha é lida por uma máquina diferente sob regras diferentes: o navegador lê o title, a codificação e as diretivas pragma pelo HTML Standard; um rastreador de busca lê description, robots e canonical pela sua própria documentação publicada e pela RFC 6596; uma plataforma social lê Open Graph pelo ogp.me e twitter:* por um registro de 2023; um consumidor de dados estruturados lê JSON-LD pela Recomendação do W3C. O que cada parte exige, o que apenas prefere, o que é ignorado em silêncio, e o punhado de regras (um title, uma description, UTF-8 uma vez e cedo, exatamente um atributo identificador por meta) que são erros e não conselhos.
- [Uma Content Security Policy, lida como o navegador a lê](https://ronutz.com/pt-BR/learn/content-security-policy-read-by-the-specification.md): Um cabeçalho CSP é uma frase numa pequena linguagem formal, e o navegador o lê com um algoritmo que a especificação soletra: dividir nos pontos e vírgulas, passar os nomes a minúsculas, ignorar uma diretiva que se repete, ler cada token de um valor contra uma gramática. A maioria das políticas quebradas quebra exatamente nesses passos, e em silêncio: uma palavra-chave sem aspas vira nome de host, um ponto e vírgula faltando funde duas diretivas numa só, um default-src que parece protetor não governa nada depois que script-src é definido, 'unsafe-inline' ao lado de um nonce é ignorado sem aviso. Aqui está a leitura do próprio CSP Level 3, passo a passo, com a cadeia de recurso, as regras de casamento para curingas, esquemas e endereços IP, o que 'strict-dynamic' desliga, e a política de três diretivas que a própria especificação chama de Strict CSP.
