El DOM (Document Object Model) permite que JavaScript lea y modifique el contenido de una página HTML. Con él podemos responder a eventos, cambiar textos, crear elementos, validar formularios y construir interfaces dinámicas.
En esta guía vas a practicar con 20 ejercicios resueltos de DOM en JavaScript, desde cambios simples de contenido hasta componentes como tabs, modales, listas de tareas, tablas y filtros en tiempo real.
Si necesitás repasar la teoría primero, consultá DOM en JavaScript: seleccionar, modificar y crear elementos HTML. También podés revisar 20 ejercicios resueltos de JavaScript para principiantes.
Cómo probar los ejercicios
Para practicar cómodamente, podés crear dos archivos: index.html y app.js. En index.html, vinculá JavaScript justo antes de cerrar </body>:
<script src="app.js"></script>
En cada ejercicio te mostramos el HTML base mínimo que necesita el ejemplo. Reemplazá el contenido del <body> por ese fragmento y copiá el JavaScript correspondiente dentro de app.js.
Cuando aparezca un bloque <style>, podés dejarlo dentro del HTML para probar rápidamente el ejemplo. En un proyecto real, lo habitual es mover esos estilos a un archivo CSS separado.
Índice de ejercicios
- Cambiar el texto de un elemento
- Cambiar el color de un elemento
- Mostrar y ocultar un elemento
- Contador de clics
- Agregar elementos a una lista
- Eliminar elementos de una lista
- Leer el valor de un input
- Validar un campo obligatorio
- Contador de caracteres
- Filtrar una lista en tiempo real
- Crear pestañas (tabs)
- Crear un acordeón
- Crear un modal
- Cambiar una imagen dinámicamente
- Crear una lista de tareas
- Marcar tareas como completadas
- Crear una tabla dinámica
- Ordenar una lista desde un botón
- Carrito básico en el DOM
- Mini proyecto: buscador con filtro y contador
1. Cambiar el texto de un elemento
Enunciado: Modificar el contenido de un párrafo al presionar un botón.
HTML base
<button id="cambiar">Cambiar texto</button> <p id="texto">Texto original</p>
JavaScript
const boton = document.querySelector("#cambiar"); const texto = document.querySelector("#texto"); boton.addEventListener("click", function () { texto.textContent = "Texto actualizado"; });
querySelector() devuelve el primer elemento que coincide con el selector. textContent permite leer o cambiar su texto.
2. Cambiar el color de un elemento
Enunciado: Modificar el color de un título al hacer clic.
HTML base
<h2 id="titulo">Hacé clic sobre este título</h2>
JavaScript
const titulo = document.querySelector("#titulo"); titulo.addEventListener("click", function () { titulo.style.color = "red"; });
La propiedad style permite modificar estilos inline desde JavaScript. Para cambios más grandes suele ser mejor agregar o quitar clases CSS.
3. Mostrar y ocultar un elemento
Enunciado: Alternar la visibilidad de un bloque.
HTML base
<button id="toggle">Mostrar / ocultar</button> <div id="caja">Contenido visible</div> <style> .oculto { display: none; } </style>
JavaScript
const boton = document.querySelector("#toggle"); const caja = document.querySelector("#caja"); boton.addEventListener("click", function () { caja.classList.toggle("oculto"); });
classList.toggle() agrega la clase si no existe y la elimina si ya está presente.
4. Contador de clics
Enunciado: Contar cuántas veces se presiona un botón.
HTML base
<button id="contador">Contar clic</button> <p id="salida">0</p>
JavaScript
const boton = document.querySelector("#contador"); const salida = document.querySelector("#salida"); let cantidad = 0; boton.addEventListener("click", function () { cantidad++; salida.textContent = cantidad; });
El evento click incrementa una variable y luego actualiza el DOM.
5. Agregar elementos a una lista
Enunciado: Crear nuevos elementos li dinámicamente.
HTML base
<button id="agregar">Agregar elemento</button> <ul id="lista"></ul>
JavaScript
const lista = document.querySelector("#lista"); const boton = document.querySelector("#agregar"); boton.addEventListener("click", function () { const item = document.createElement("li"); item.textContent = "Nuevo elemento"; lista.appendChild(item); });
createElement() crea un nodo y appendChild() lo agrega al final de otro elemento.
6. Eliminar elementos de una lista
Enunciado: Eliminar un elemento al presionar un botón dentro del mismo.
HTML base
<ul id="lista"> <li>Elemento 1 <button class="eliminar">Eliminar</button></li> <li>Elemento 2 <button class="eliminar">Eliminar</button></li> </ul>
JavaScript
const lista = document.querySelector("#lista"); lista.addEventListener("click", function (evento) { if (evento.target.matches(".eliminar")) { evento.target.parentElement.remove(); } });
Este ejemplo usa delegación de eventos: el listener está en la lista y detecta qué elemento originó el clic.
7. Leer el valor de un input
Enunciado: Mostrar lo escrito en un campo de texto.
HTML base
<input id="nombre" type="text" placeholder="Escribí tu nombre"> <button id="mostrar">Mostrar</button> <p id="salida"></p>
JavaScript
const input = document.querySelector("#nombre"); const boton = document.querySelector("#mostrar"); const salida = document.querySelector("#salida"); boton.addEventListener("click", function () { salida.textContent = input.value; });
La propiedad value devuelve el contenido actual de un campo de formulario.
8. Validar un campo obligatorio
Enunciado: Evitar aceptar un formulario si un campo está vacío.
HTML base
<form id="formulario"> <input id="nombre" type="text" placeholder="Nombre"> <button type="submit">Enviar</button> </form> <p id="mensaje"></p>
JavaScript
const formulario = document.querySelector("#formulario"); const nombre = document.querySelector("#nombre"); const mensaje = document.querySelector("#mensaje"); formulario.addEventListener("submit", function (evento) { evento.preventDefault(); if (nombre.value.trim() === "") { mensaje.textContent = "El nombre es obligatorio"; return; } mensaje.textContent = "Formulario válido"; });
preventDefault() evita el envío automático. trim() elimina espacios al principio y al final.
9. Contador de caracteres
Enunciado: Mostrar cuántos caracteres escribió el usuario.
HTML base
<textarea id="mensaje" placeholder="Escribí un mensaje"></textarea> <p>Caracteres: <span id="contador">0</span></p>
JavaScript
const textarea = document.querySelector("#mensaje"); const contador = document.querySelector("#contador"); textarea.addEventListener("input", function () { contador.textContent = textarea.value.length; });
El evento input se dispara cuando cambia el valor del campo, incluso al pegar texto.
10. Filtrar una lista en tiempo real
Enunciado: Mostrar sólo los elementos que coinciden con la búsqueda.
HTML base
<input id="buscar" type="text" placeholder="Buscar..."> <ul id="lista"> <li>JavaScript</li> <li>Python</li> <li>PHP</li> <li>Laravel</li> </ul>
JavaScript
const buscador = document.querySelector("#buscar"); const items = document.querySelectorAll("#lista li"); buscador.addEventListener("input", function () { const texto = buscador.value.toLowerCase(); items.forEach(function (item) { const coincide = item.textContent.toLowerCase().includes(texto); item.style.display = coincide ? "" : "none"; }); });
querySelectorAll() devuelve una colección de elementos. Luego usamos forEach() para evaluar cada uno.
11. Crear pestañas (tabs)
Enunciado: Cambiar el contenido visible según la pestaña seleccionada.
HTML base
<button class="tab" data-panel="panel1">Pestaña 1</button> <button class="tab" data-panel="panel2">Pestaña 2</button> <div id="panel1" class="panel">Contenido 1</div> <div id="panel2" class="panel oculto">Contenido 2</div> <style> .oculto { display: none; } </style>
JavaScript
const botones = document.querySelectorAll(".tab"); const paneles = document.querySelectorAll(".panel"); botones.forEach(function (boton) { boton.addEventListener("click", function () { paneles.forEach(function (panel) { panel.classList.add("oculto"); }); const id = boton.dataset.panel; document.querySelector("#" + id).classList.remove("oculto"); }); });
dataset permite leer atributos data-*. Es útil para relacionar controles con elementos del DOM.
12. Crear un acordeón
Enunciado: Abrir y cerrar secciones de contenido.
HTML base
<button class="acordeon">Sección 1</button> <div>Contenido de la sección 1</div> <button class="acordeon">Sección 2</button> <div class="oculto">Contenido de la sección 2</div> <style> .oculto { display: none; } </style>
JavaScript
const botones = document.querySelectorAll(".acordeon"); botones.forEach(function (boton) { boton.addEventListener("click", function () { const contenido = boton.nextElementSibling; contenido.classList.toggle("oculto"); }); });
nextElementSibling devuelve el siguiente elemento hermano dentro del DOM.
13. Crear un modal
Enunciado: Mostrar y cerrar una ventana modal.
HTML base
<button id="abrirModal">Abrir modal</button> <div id="modal" class="oculto"> <div> <p>Contenido del modal</p> <button id="cerrarModal">Cerrar</button> </div> </div> <style> .oculto { display: none; } </style>
JavaScript
const abrir = document.querySelector("#abrirModal"); const cerrar = document.querySelector("#cerrarModal"); const modal = document.querySelector("#modal"); abrir.addEventListener("click", function () { modal.classList.remove("oculto"); }); cerrar.addEventListener("click", function () { modal.classList.add("oculto"); });
El modal se controla cambiando una clase CSS. Esta técnica mantiene separadas la lógica y la presentación.
14. Cambiar una imagen dinámicamente
Enunciado: Modificar el atributo src de una imagen.
HTML base
<img id="imagen" src="imagen-1.jpg" alt="Imagen de ejemplo"> <button id="cambiarImagen">Cambiar imagen</button>
JavaScript
const imagen = document.querySelector("#imagen"); const boton = document.querySelector("#cambiarImagen"); boton.addEventListener("click", function () { imagen.setAttribute("src", "imagen-2.jpg"); });
setAttribute() modifica un atributo HTML. También podría escribirse directamente imagen.src = ....
15. Crear una lista de tareas
Enunciado: Agregar tareas desde un formulario.
HTML base
<form id="formTarea"> <input id="tarea" type="text" placeholder="Nueva tarea"> <button type="submit">Agregar</button> </form> <ul id="listaTareas"></ul>
JavaScript
const formulario = document.querySelector("#formTarea"); const input = document.querySelector("#tarea"); const lista = document.querySelector("#listaTareas"); formulario.addEventListener("submit", function (evento) { evento.preventDefault(); const texto = input.value.trim(); if (texto === "") { return; } const item = document.createElement("li"); item.textContent = texto; lista.appendChild(item); input.value = ""; });
El ejemplo combina eventos, validación, creación de nodos y actualización del DOM.
16. Marcar tareas como completadas
Enunciado: Alternar el estado visual de una tarea.
HTML base
<ul id="listaTareas"> <li>Estudiar JavaScript</li> <li>Practicar DOM</li> </ul> <style> .completada { text-decoration: line-through; opacity: .6; } </style>
JavaScript
const lista = document.querySelector("#listaTareas"); lista.addEventListener("click", function (evento) { if (evento.target.matches("li")) { evento.target.classList.toggle("completada"); } });
La delegación de eventos permite que también funcionen las tareas creadas dinámicamente después de cargar la página.
17. Crear una tabla dinámica
Enunciado: Generar filas a partir de un array de objetos.
HTML base
<table id="tablaUsuarios"> <thead> <tr> <th>Nombre</th> <th>Edad</th> </tr> </thead> <tbody></tbody> </table>
JavaScript
const usuarios = [ { nombre: "Ana", edad: 28 }, { nombre: "Luis", edad: 34 }, { nombre: "Marta", edad: 25 } ]; const cuerpo = document.querySelector("#tablaUsuarios tbody"); usuarios.forEach(function (usuario) { const fila = document.createElement("tr"); fila.innerHTML = "<td>" + usuario.nombre + "</td>" + "<td>" + usuario.edad + "</td>"; cuerpo.appendChild(fila); });
innerHTML permite insertar HTML. Si los datos provienen de usuarios o fuentes externas, hay que evitar insertar contenido no confiable sin sanitizar.
18. Ordenar una lista desde un botón
Enunciado: Ordenar elementos alfabéticamente y volver a renderizarlos.
HTML base
<button id="ordenar">Ordenar</button> <ul id="lista"> <li>Python</li> <li>JavaScript</li> <li>CSS</li> <li>HTML</li> </ul>
JavaScript
const lista = document.querySelector("#lista"); const boton = document.querySelector("#ordenar"); boton.addEventListener("click", function () { const items = [...lista.querySelectorAll("li")]; items.sort(function (a, b) { return a.textContent.localeCompare(b.textContent); }); items.forEach(function (item) { lista.appendChild(item); }); });
Convertimos la colección a array con ... para poder usar sort(). Al volver a agregar los nodos, el DOM cambia de orden.
19. Carrito básico en el DOM
Enunciado: Agregar productos a un carrito y actualizar el total.
HTML base
<button class="agregar" data-precio="25">Agregar Mouse ($25)</button> <button class="agregar" data-precio="60">Agregar Teclado ($60)</button> <p>Total: $<span id="total">0</span></p>
JavaScript
const botones = document.querySelectorAll(".agregar"); const totalElemento = document.querySelector("#total"); let total = 0; botones.forEach(function (boton) { boton.addEventListener("click", function () { const precio = Number(boton.dataset.precio); total += precio; totalElemento.textContent = total; }); });
dataset.precio devuelve texto, por eso usamos Number() antes de sumarlo.
20. Mini proyecto: buscador con filtro y contador
Enunciado: Crear un buscador que filtre tarjetas y muestre cuántos resultados quedan visibles.
HTML base
<input id="buscar" type="text" placeholder="Buscar usuario..."> <p>Resultados: <span id="cantidad">0</span></p> <div class="tarjeta">Ana García - ana@example.com</div> <div class="tarjeta">Luis Pérez - luis@example.com</div> <div class="tarjeta">Marta López - marta@example.com</div>
JavaScript
const buscador = document.querySelector("#buscar"); const tarjetas = document.querySelectorAll(".tarjeta"); const contador = document.querySelector("#cantidad"); function filtrar() { const texto = buscador.value.toLowerCase(); let visibles = 0; tarjetas.forEach(function (tarjeta) { const coincide = tarjeta.textContent.toLowerCase().includes(texto); tarjeta.style.display = coincide ? "" : "none"; if (coincide) { visibles++; } }); contador.textContent = visibles; } buscador.addEventListener("input", filtrar); filtrar();
El ejercicio combina búsqueda en tiempo real, recorrido de elementos, actualización visual y un contador de resultados.
Conceptos de DOM que practicamos
A lo largo de los ejercicios usamos querySelector(), querySelectorAll(), addEventListener(), textContent, value, classList, dataset, createElement(), appendChild(), innerHTML y delegación de eventos.
La idea es que no memorices cada línea, sino que identifiques el patrón: seleccionar un elemento, escuchar un evento, modificar el estado y reflejar ese cambio en el DOM.
Seguí aprendiendo JavaScript
- Guía completa de JavaScript
- 20 ejercicios resueltos de JavaScript para principiantes
- 20 ejercicios resueltos de arrays en JavaScript
- 20 ejercicios avanzados de JavaScript
- Eventos y formularios en JavaScript
¿Te sirvió esta guía? ☕
Si este contenido te ayudó a aprender JavaScript, podés apoyar a Club Programador. Cada aporte ayuda a mantener el sitio online y a seguir publicando material gratuito.
🇦🇷 Apoyar desde Argentina
☕ Invitame un café con Mercado Pago
🌎 Apoyar desde otro país
Descubre más desde Club Programador
Suscríbete y recibe las últimas entradas en tu correo electrónico.