DOM — Document Object Model

El DOM es la representación del HTML como un árbol de objetos que JavaScript puede leer y modificar. Es la base de toda interactividad en el navegador.

¿Qué es el DOM?

Cuando el navegador carga una página HTML, construye una estructura en memoria llamada DOM (Document Object Model). Es un árbol de nodos donde cada etiqueta HTML es un objeto que JavaScript puede seleccionar, modificar, crear o eliminar.

<!-- HTML -->
<div id="contenedor">
    <h1 class="titulo">Hola</h1>
    <p>Primer párrafo</p>
    <p>Segundo párrafo</p>
</div>
// JavaScript puede acceder a cualquier elemento
const contenedor = document.getElementById("contenedor");
const titulo     = document.querySelector(".titulo");
const parrafos   = document.querySelectorAll("p");
document

document es el objeto raíz del DOM — representa toda la página. A partir de él podés llegar a cualquier elemento.

Seleccionar elementos

// Por ID — devuelve un elemento o null
const titulo = document.getElementById("mi-titulo");

// Por selector CSS — devuelve el PRIMERO que coincide
const primero = document.querySelector(".card");
const input   = document.querySelector("input[type='text']");
const h2      = document.querySelector("#seccion h2");

// Por selector CSS — devuelve TODOS (NodeList)
const cards   = document.querySelectorAll(".card");
const inputs  = document.querySelectorAll("input");

// Iterar sobre una NodeList
cards.forEach(card => {
    console.log(card.textContent);
});

// Métodos más antiguos (aún funcionan)
document.getElementsByClassName("card");  // HTMLCollection
document.getElementsByTagName("p");       // HTMLCollection
querySelector vs getElementById

querySelector acepta cualquier selector CSS — es más flexible. getElementById es más rápido pero solo busca por ID. En la práctica, querySelector se usa para casi todo.

Probá el Ejemplo 1: Seleccionar y leer elementos

Leer y modificar contenido

const el = document.getElementById("caja");

// Leer
el.textContent;     // texto plano (sin HTML)
el.innerHTML;       // contenido con etiquetas HTML
el.value;           // valor de inputs y textareas

// Modificar
el.textContent = "Nuevo texto";
el.innerHTML   = "<strong>Texto en negrita</strong>";

// Atributos
el.getAttribute("class");
el.setAttribute("class", "activo");
el.removeAttribute("disabled");
el.id;             // leer el id directamente
el.href;           // leer href de un enlace

// Dataset — atributos data-*
// <div data-usuario="ana" data-rol="admin">
el.dataset.usuario;  // "ana"
el.dataset.rol;      // "admin"
Probá el Ejemplo 2: Modificar contenido y atributos

Modificar estilos y clases

const caja = document.getElementById("caja");

// Estilos inline — directamente sobre el elemento
caja.style.color           = "red";
caja.style.backgroundColor = "#f0f0f0";  // camelCase
caja.style.fontSize        = "18px";
caja.style.display         = "none";     // ocultar
caja.style.display         = "";         // restaurar al valor CSS

// Clases — la forma recomendada (separa JS del CSS)
caja.classList.add("activo");
caja.classList.remove("inactivo");
caja.classList.toggle("visible");       // agrega si no está, quita si está
caja.classList.contains("activo");      // true/false
caja.classList.replace("viejo", "nuevo");

// Múltiples clases
caja.classList.add("grande", "rojo", "centrado");
classList en vez de style

Preferí manipular clases CSS con classList en vez de modificar style directamente. Así mantenés los estilos en el CSS y el JS solo controla la lógica.

Crear y eliminar elementos

// Crear un elemento nuevo
const li = document.createElement("li");
li.textContent  = "Nuevo item";
li.className    = "item-lista";

// Agregarlo al DOM
const lista = document.getElementById("mi-lista");
lista.appendChild(li);                  // al final
lista.prepend(li);                      // al principio
lista.insertBefore(li, lista.children[2]); // antes del 3er hijo

// Forma moderna con insertAdjacentHTML
lista.insertAdjacentHTML("beforeend", "<li>Item con HTML</li>");
lista.insertAdjacentHTML("afterbegin","<li>Primero</li>");

// Eliminar elementos
const item = document.querySelector(".item-a-borrar");
item.remove();                          // forma moderna
// item.parentNode.removeChild(item);  // forma antigua

// Clonar un elemento
const clon = li.cloneNode(true);  // true = clonar también hijos
lista.appendChild(clon);
Probá el Ejemplo 3: Crear y eliminar elementos

Navegar el árbol DOM

const el = document.getElementById("item");

// Subir
el.parentElement;           // elemento padre
el.parentElement.parentElement; // abuelo

// Bajar
el.children;                // HTMLCollection de hijos directos
el.firstElementChild;       // primer hijo
el.lastElementChild;        // último hijo
el.children[2];             // tercer hijo

// Ir al costado
el.nextElementSibling;      // siguiente hermano
el.previousElementSibling;  // hermano anterior

// Buscar dentro de un elemento (no en todo el documento)
const contenedor = document.getElementById("contenedor");
contenedor.querySelector(".item");       // busca solo adentro
contenedor.querySelectorAll("li");

Ejemplo Completo — Lista de tareas dinámica

Una mini app que crea, completa y elimina tareas manipulando el DOM:

function agregarTarea(texto) {
    if (!texto.trim()) return;

    const li = document.createElement("li");
    li.className = "tarea";

    const span = document.createElement("span");
    span.textContent = texto;

    const btnCompletar = document.createElement("button");
    btnCompletar.textContent = "✓";
    btnCompletar.onclick = () => li.classList.toggle("completada");

    const btnBorrar = document.createElement("button");
    btnBorrar.textContent = "✕";
    btnBorrar.onclick = () => li.remove();

    li.append(span, btnCompletar, btnBorrar);
    document.getElementById("lista").appendChild(li);
}

// Leer valor de un input y agregar
const input = document.getElementById("nuevaTarea");
document.getElementById("btnAgregar").onclick = () => {
    agregarTarea(input.value);
    input.value = "";
    input.focus();
};
Probá el Ejemplo 4: Lista de tareas

Buenas Prácticas

  • querySelector sobre getElementById: más flexible y acepta cualquier selector CSS
  • classList sobre style: separá la lógica (JS) del diseño (CSS)
  • Guardá referencias en variables: no llames a getElementById dentro de un loop — es lento
  • insertAdjacentHTML para insertar muchos elementos: más eficiente que múltiples appendChild
  • Verificá que el elemento existe: antes de manipularlo, comprobá que no sea null
  • Delegación de eventos: en vez de poner listeners en cada elemento hijo, poné uno en el padre (lo verás en el tuto de Eventos)