RETO 1
Tarjeta semántica
Construye una ficha con título, descripción y enlace. Distingue
acción y navegación.
Ver pista
Un article funciona si la ficha tiene sentido por sí sola.
Ver solución de referencia
HTML
<article><h2>Mi curso</h2><p>Aprende una idea cada día.</p><a href="#">Leer más</a></article>
CSS
article { padding: 24px; border: 1px solid #ddd; border-radius: 16px; }
Probar este reto Lo practiqué
y lo entendí
<article><h2>Mi curso</h2><p>Aprende una idea cada día.</p><a href="#">Leer más</a></article>
article { padding: 24px; border: 1px solid #ddd; border-radius: 16px; }
RETO 2
Formulario etiquetado
Añade una etiqueta, una instrucción y un campo requerido. Explica
el resultado del envío local.
Ver pista
Asocia label y control por id y for.
Ver solución de referencia
HTML
<form id="form"><label for="nombre">Nombre</label><input id="nombre" required><button>Comprobar</button><p id="respuesta" role="status"></p></form>
CSS
input, button { padding: 12px; margin: 8px; }
JavaScript
document.querySelector("#form").addEventListener("submit", e => { e.preventDefault(); document.querySelector("#respuesta").textContent = "Formulario válido. No se envían datos."; });
Probar este reto Lo practiqué
y lo entendí
<form id="form"><label for="nombre">Nombre</label><input id="nombre" required><button>Comprobar</button><p id="respuesta" role="status"></p></form>
input, button { padding: 12px; margin: 8px; }
document.querySelector("#form").addEventListener("submit", e => { e.preventDefault(); document.querySelector("#respuesta").textContent = "Formulario válido. No se envían datos."; });
RETO 3
Galería adaptable
Muestra tres tarjetas y apílalas cuando el espacio sea pequeño.
Ver pista
Prueba repeat, minmax y auto-fit.
Ver solución de referencia
HTML
<section class="grid"><article>Uno</article><article>Dos</article><article>Tres</article></section>
CSS
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); gap: 16px; } article { padding: 24px; background: #eef1ff; }
Probar este reto Lo practiqué
y lo entendí
<section class="grid"><article>Uno</article><article>Dos</article><article>Tres</article></section>
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); gap: 16px; } article { padding: 24px; background: #eef1ff; }
RETO 4
Menú desplegable
Haz que un botón muestre una lista y actualice aria-expanded.
Ver pista
Cambia el estado y la presentación juntos.
Ver solución de referencia
HTML
<button id="menu" aria-controls="enlaces" aria-expanded="false">Menú</button><nav id="enlaces" hidden><a href="#">Inicio</a><a href="#">Ayuda</a></nav>
CSS
button, a { padding: 12px; } a { display: block; } [hidden] { display: none; }
JavaScript
const boton = document.querySelector("#menu"); const nav = document.querySelector("#enlaces"); boton.addEventListener("click", () => { const abierto = boton.getAttribute("aria-expanded") !== "true"; boton.setAttribute("aria-expanded", abierto); nav.hidden = !abierto; });
Probar este reto Lo practiqué
y lo entendí
RETO 5
Contador con estado
Suma, resta y reinicia un número. Mantén el estado en una
variable.
Ver pista
Primero cambia el valor; después actualiza output.
Ver solución de referencia
HTML
<button id="menos">Restar</button><output id="valor">0</output><button id="mas">Sumar</button><button id="reset">Reiniciar</button>
CSS
button { padding: 12px; } output { padding: 20px; font-size: 32px; }
JavaScript
let n = 0; const salida = document.querySelector("#valor"); function mostrar() { salida.value = n; } document.querySelector("#mas").onclick = () => { n++; mostrar(); }; document.querySelector("#menos").onclick = () => { n--; mostrar(); }; document.querySelector("#reset").onclick = () => { n = 0; mostrar(); };
Probar este reto Lo
practiqué y lo entendí
<button id="menos">Restar</button><output id="valor">0</output><button id="mas">Sumar</button><button id="reset">Reiniciar</button>
button { padding: 12px; } output { padding: 20px; font-size: 32px; }
let n = 0; const salida = document.querySelector("#valor"); function mostrar() { salida.value = n; } document.querySelector("#mas").onclick = () => { n++; mostrar(); }; document.querySelector("#menos").onclick = () => { n--; mostrar(); }; document.querySelector("#reset").onclick = () => { n = 0; mostrar(); };
RETO 6
Lista con buscador
Filtra una lista al escribir, sin distinguir mayúsculas. Añade un
estado sin resultados.
Ver pista
Lee el texto del control y compara cada elemento.
Ver solución de referencia
HTML
<label>Buscar <input id="buscar"></label><ul><li>HTML</li><li>CSS</li><li>JavaScript</li></ul><p id="estado" role="status"></p>
CSS
input { padding: 12px; } li { padding: 8px; }
JavaScript
document.querySelector("#buscar").addEventListener("input", e => { let total = 0; document.querySelectorAll("li").forEach(li => { li.hidden = !li.textContent.toLowerCase().includes(e.target.value.toLowerCase()); if (!li.hidden) total++; }); document.querySelector("#estado").textContent = total ? `${total} resultados` : "Sin resultados"; });
Probar este reto Lo
practiqué y lo entendí
<label>Buscar <input id="buscar"></label><ul><li>HTML</li><li>CSS</li><li>JavaScript</li></ul><p id="estado" role="status"></p>
input { padding: 12px; } li { padding: 8px; }
document.querySelector("#buscar").addEventListener("input", e => { let total = 0; document.querySelectorAll("li").forEach(li => { li.hidden = !li.textContent.toLowerCase().includes(e.target.value.toLowerCase()); if (!li.hidden) total++; }); document.querySelector("#estado").textContent = total ? `${total} resultados` : "Sin resultados"; });