Browser APIs

O DOM

O Document Object Model é a ponte entre seu HTML e seu JavaScript. Aprenda a selecionar, criar, atualizar e remover elementos, e como reagir às ações dos usuários.

beginner15 min readUpdated 15 de set. de 2026
js
const list = document.querySelector("#todos");
const input = document.querySelector("#todo-input");

function addTodo(text) {
  const li = document.createElement("li");
  li.textContent = text;
  list.append(li);
}

input.addEventListener("keydown", (event) => {
  if (event.key === "Enter") {
    addTodo(input.value);
    input.value = "";
  }
});
O que é
Uma árvore viva de objetos
Construído por
O navegador, a partir do seu HTML
Selecione com
querySelector / querySelectorAll
Reaja com
addEventListener
Crie com
document.createElement
Custo
Trabalho de layout e paint

Pratico

Experimente a manipulação do DOM

Clique no botão e depois edite o código para ver como a árvore muda.

Experimente a manipulação do DOM

Clique no botão e depois edite o código para ver como a árvore muda.

Por que importa

Por que o DOM é importante

Seu HTML como objetos

O navegador analisa a marcação e a transforma em uma árvore de nós que seu código pode ler e alterar a qualquer momento.

Feedback instantâneo

Atualize a árvore e o navegador redesenha a tela automaticamente — sem recarregar a página, sem requisições ao servidor.

Reaja a qualquer coisa

Cliques, digitação, rolagem, redimensionamento, eventos de rede e muito mais chegam através de um único modelo de eventos.

O panorama completo

As três ideias por trás do DOM

Toda tarefa no DOM é uma combinação dos mesmos três movimentos: encontrar algo, alterá-lo ou reagir a ele.

A árvore

Estrutura

Uma hierarquia de nós onde cada elemento, atributo e trecho de texto tem um lugar e um pai.

Seleção

Encontrar e alterar

Consulte a árvore e, em seguida, leia ou escreva textos, atributos, classes e estilos nos nós encontrados.

Eventos

Reagir

Escute eventos do usuário e do navegador, e então execute código em resposta — idealmente usando delegação.

DOM em resumo

O que você pode fazer com o DOM

Selecionando elementos

querySelector retorna a primeira correspondência, querySelectorAll retorna todas as correspondências como uma lista estática.

Leitura e escrita

textContent, innerHTML, atributos e dataset permitem inspecionar e atualizar o conteúdo.

Classes e estilos

classList e a propriedade style alteram a aparência sem tocar em uma folha de estilo.

Construindo nós

createElement, append, prepend e remove expandem ou reduzem a árvore sob demanda.

Eventos

addEventListener assina cliques, input, teclado, scroll e muito mais.

Delegação de eventos

Um único listener em um elemento pai pode lidar com eventos de todos os seus filhos, mesmo aqueles adicionados posteriormente.

Uma breve historia

A evolução do DOM

  1. 1996

    O primeiro DOM

    Netscape e Microsoft expõem formas concorrentes de criar scripts em páginas, iniciando a primeira guerra dos navegadores.

    96
  2. 1998

    DOM Level 1

    O W3C padroniza um modelo de árvore comum e uma API compartilhada para manipulá-la.

    98
  3. 2009

    Chegada do querySelector

    Seletores no estilo CSS tornam a busca de elementos drasticamente mais simples e expressiva.

    09
  4. 2015

    classList e APIs modernas

    classList, dataset e template simplificam o trabalho diário com o DOM e substituem gambiarras antigas.

    15
  5. Hoje

    Um padrão vivo

    O DOM é mantido como uma especificação continuamente atualizada com amplo consenso entre os navegadores.

    Hoje

O guia completo

O DOM: Tudo que voce precisa saber

O que é o DOM?

Quando o navegador lê o seu HTML, ele não mantém apenas uma string de texto simples. Ele constrói uma árvore de objetos chamada Document Object Model. Cada elemento torna-se um nó com propriedades e métodos, cada atributo fica acessível e cada trecho de texto tem o seu lugar. O DOM é essa árvore, e ela é dinâmica: altere-a e a página será atualizada.

É por isso que o JavaScript e o HTML parecem conectados. O seu HTML descreve a estrutura, o navegador a transforma em objetos e o JavaScript manipula esses objetos. O objeto document é o ponto de entrada para toda a árvore.

A árvore de nós

O DOM é hierárquico. O document é a raiz, o <html> é seu filho, e todo o restante está pendurado abaixo em uma relação de pai e filho. Um nó pode ter muitos filhos, mas apenas um pai.

document
└── html
    ├── head
    │   └── title
    └── body
        ├── h1
        └── p

Existem vários tipos de nós. Nós de elemento representam tags. Nós de texto contêm os caracteres dentro dos elementos. Nós de comentário representam comentários. Na maioria das vezes, você trabalhará com elementos, mas saber que os nós de texto existem explica surpresas com espaços em branco e por que o childNodes pode incluir mais do que você espera.

Selecionando elementos

Antes de alterar qualquer coisa, você precisa encontrá-la. A ferramenta principal moderna é querySelector, que aceita qualquer seletor CSS.

// select.js
const title = document.querySelector("h1");
const firstCard = document.querySelector(".card");
const allLinks = document.querySelectorAll("a[target='_blank']");
const byId = document.getElementById("main");

allLinks.forEach((link) => link.classList.add("external"));

querySelector retorna o primeiro elemento correspondente ou null. querySelectorAll retorna uma NodeList estática de todas as correspondências, que suporta forEach, mas não é atualizada quando o DOM muda. Os métodos mais antigos getElementById, getElementsByClassName e getElementsByTagName ainda funcionam; os dois últimos retornam coleções vivas (live collections) que são atualizadas automaticamente.

Lendo e escrevendo conteúdo

Assim que você tiver um elemento, poderá ler ou substituir o conteúdo dele.

// content.js
const heading = document.querySelector("#title");

heading.textContent;          // read the visible text
heading.textContent = "Hello"; // replace it, escaped as text

heading.innerHTML = "<em>Hi</em>"; // parses HTML

Use textContent sempre que o valor vier de um usuário, de uma API ou de qualquer lugar que você não controle totalmente. Ele trata tudo como texto simples e não permite a injeção de marcação. innerHTML analisa uma string como HTML, o que é conveniente para templates confiáveis, mas representa um risco sério de cross-site scripting com entradas não confiáveis. Se você precisar construir marcação a partir de dados, prefira criar elementos e definir textContent em cada um.

Atributos, classes e estilos

Os atributos ficam no elemento e podem ser lidos ou alterados diretamente.

// attrs.js
const link = document.querySelector("a");

link.getAttribute("href");
link.setAttribute("href", "/docs");
link.dataset.userId = "42"; // data-user-id="42"

link.classList.add("active");
link.classList.toggle("open");
link.classList.remove("hidden");

link.style.color = "tomato";

classList é a maneira mais limpa de gerenciar classes — isso evita a concatenação de strings e a criação acidental de classes duplicadas. A propriedade style define estilos inline, uma propriedade por vez; para qualquer coisa temática, prefira alternar uma classe e deixar o CSS decidir.

Criando, inserindo e removendo nós

Você cria novos nós com document.createElement e os posiciona utilizando os métodos de inserção.

// build.js
const item = document.createElement("li");
item.textContent = "New task";
item.classList.add("task");

const list = document.querySelector("#todos");
list.append(item);       // add at the end
list.prepend(item);      // add at the start
item.remove();           // detach from the tree

append aceita múltiplos nós e até strings, enquanto insertBefore oferece um posicionamento preciso. Quando você precisar inserir muitos nós, crie-os fora do documento e anexe-os de uma só vez:

// fragment.js
const fragment = document.createDocumentFragment();
for (const name of names) {
  const li = document.createElement("li");
  li.textContent = name;
  fragment.append(li);
}
list.append(fragment);

Um DocumentFragment é um container leve que não faz parte da página. Anexá-lo move todos os seus filhos em uma única operação, o que dispara muito menos trabalho de layout do que adicioná-los um por um.

Escutando eventos

Eventos são a forma como seu código responde ao usuário e ao navegador. Anexe um listener com addEventListener.

// events.js
const button = document.querySelector("#save");

button.addEventListener("click", (event) => {
  event.preventDefault();
  console.log("clicked", event.target);
});

O objeto de evento carrega informações úteis: target é o elemento que disparou o evento, currentTarget é o elemento ao qual o listener está anexado, e preventDefault() cancela o comportamento padrão do navegador. Eventos comuns incluem click, input, change, submit, keydown, scroll e DOMContentLoaded.

Delegação de eventos

Em vez de adicionar um listener para cada filho, adicione um ao elemento pai e inspecione event.target. Como os eventos fazem o bubble (propagam-se) do alvo para cima através de seus ancestrais, o pai consegue visualizar todos eles.

// delegate.js
const list = document.querySelector("#todos");

list.addEventListener("click", (event) => {
  const button = event.target.closest("button.delete");
  if (!button) return;
  button.closest("li").remove();
});

Isso é mais eficiente e, crucialmente, continua funcionando para elementos adicionados após o listener ter sido configurado. Para listas e tabelas dinâmicas, a delegação é o padrão recomendado.

Percorrendo a árvore

Às vezes, você precisa se mover de um nó para seus parentes.

// traverse.js
const item = document.querySelector(".item");

item.parentElement;        // nearest ancestor element
item.children;             // child elements only
item.firstElementChild;    // first child element
item.nextElementSibling;   // next sibling element
item.closest(".card");     // nearest ancestor matching a selector

As variantes Element ignoram nós de texto e de comentário, que é quase sempre o que você deseja. closest é especialmente útil em manipuladores de eventos, como mostra o exemplo de delegação.

Performance e boas práticas

  • Agrupe suas leituras e escritas. Ler propriedades de layout como offsetHeight força o navegador a recalcular; intercalar leituras e escritas causa reflows repetidos.
  • Construa fora do documento. Use um DocumentFragment ou um elemento fora da tela e, então, anexe-o apenas uma vez.
  • Faça cache de suas buscas. Armazene elementos em variáveis em vez de realizar queries dentro de um loop.
  • Prefira classes a estilos inline. Alterne uma classe e mantenha a apresentação no CSS.
  • Use textContent por padrão. Use innerHTML apenas com conteúdo confiável e sanitizado.
  • Delegue eventos para listas e qualquer elemento dinâmico.
  • Remova listeners que você não precisa mais, especialmente em páginas de longa duração, para evitar leaks.

Erros comuns

  • Consultar um elemento antes que ele exista e depois se perguntar por que ele é null.
  • Usar innerHTML com entrada de usuário e abrir uma brecha de XSS.
  • Anexar um listener a cada linha em vez de delegar para a tabela.
  • Ler e escrever propriedades de layout no mesmo loop.
  • Confundir event.target com event.currentTarget.
  • Assumir que querySelectorAll é live quando, na verdade, é um snapshot estático.

Próximos passos

O DOM é o ponto de encontro de tudo o que você aprendeu. Combine-o com a sintaxe ES6+ para ter um código mais limpo, alimente-o com dados usando a Fetch API e mantenha-o resiliente com tratamento de erros. A maneira mais rápida de internalizar esses conceitos é reconstruir algo pequeno — uma lista de tarefas, uma galeria com filtros ou uma busca em tempo real — inteiramente em vanilla JavaScript.

Definindo texto com segurança

textContent trata a entrada como texto. innerHTML a analisa como marcação, o que é um risco de XSS com dados não confiáveis.

Preferível
const comment = "<b>hi</b>";
el.textContent = comment;
// renders the literal text
Evite
const comment = "<img src=x onerror=alert(1)>";
el.innerHTML = comment;
// executes markup

Escutando cliques

Delegue para um pai para que itens adicionados posteriormente ainda funcionem e você anexe apenas um listener em vez de vários.

Preferível
list.addEventListener("click", (e) => {
  const li = e.target.closest("li");
  if (li) li.remove();
});
Evite
document.querySelectorAll("li")
  .forEach((li) => {
    li.addEventListener("click", () => li.remove());
  });

Perguntas frequentes

Perguntas frequentes

Keep learning

Related topics from the roadmap.

$ comecar a aprender

Pronto para aprender DOM Manipulation?

Nosso tutorial interativo te guia por DOM Manipulation passo a passo — com quizzes e codigo real que voce pode executar no navegador.