20 ejercicios resueltos de DOM en JavaScript

20 ejercicios resueltos de DOM en JavaScript: eventos, formularios, listas, tabs, modales, filtros, tablas y más, explicados paso a paso.


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

  1. Cambiar el texto de un elemento
  2. Cambiar el color de un elemento
  3. Mostrar y ocultar un elemento
  4. Contador de clics
  5. Agregar elementos a una lista
  6. Eliminar elementos de una lista
  7. Leer el valor de un input
  8. Validar un campo obligatorio
  9. Contador de caracteres
  10. Filtrar una lista en tiempo real
  11. Crear pestañas (tabs)
  12. Crear un acordeón
  13. Crear un modal
  14. Cambiar una imagen dinámicamente
  15. Crear una lista de tareas
  16. Marcar tareas como completadas
  17. Crear una tabla dinámica
  18. Ordenar una lista desde un botón
  19. Carrito básico en el DOM
  20. 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


¿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

☕ Apoyar con PayPal


Descubre más desde Club Programador

Suscríbete y recibe las últimas entradas en tu correo electrónico.

Deja un comentario

Descubre más desde Club Programador

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo