¿Qué aprenderás?
-
Manejar elementos <audio> (métodos .play(), .pause(), .currentTime = 0).
-
Usar event delegation para no crear un listener por botón.
-
Micro-interacciones: foco de teclado, estados activos, y layout responsivo.
Código (3 archivos)
1) index.html
2) style.css
3) script.js
Arquitectura (capa por capa)
1) Estructura HTML
-
Un contenedor .grid con botones <button> (no <div>), porque:
-
Son focusables por defecto (teclado).
-
Emite eventos de “click” al presionar Enter/Space.
-
-
Cada botón tiene un atributo data-sound="ID". Ese ID coincide con el id de un <audio> en el HTML.
Ej.: <button data-sound="s1">Roar</button> ↔ <audio id="s1" src="...">.
Esto desacopla el UI del recurso; no necesitas hardcodear rutas de audio dentro del botón.
2) Estilos y layout
-
CSS Grid para que la cuadrícula responda al ancho de pantalla (repeat(auto-fit, minmax(...))).
-
Estados visuales:
-
:hover, :active, y una clase .is-playing que añadimos por JS mientras suena el audio.
-
Sombras y un leve “presionado” para que el usuario sienta el clic.
-
3) Lógica JS
-
Event delegation: en vez de asignar un addEventListener por botón, ponemos uno en el contenedor .grid y filtramos con e.target.closest('.pad').
Ventajas: menos listeners, más simple escalar a 50+ botones. -
Reproducción:
-
audio.pause() y audio.currentTime = 0 reinician la pista para evitar que se “encimen” clics rápidos.
-
audio.play() inicia. Si el navegador exige interacción previa, ya la hubo (clic/tecla), por lo que no debería bloquear.
-
-
Feedback:
-
Añadimos .is-playing al botón y la retiramos cuando el audio lanza ended.
-
Fallback con setTimeout por si el audio no emite ended (p. ej., si cambias a loop).
-
Detalles importantes y pitfalls
Autoplay / políticas de los navegadores
-
La mayoría de navegadores bloquean play() hasta que haya interacción del usuario (clic, tecla).
-
En este proyecto disparas play() desde el handler del clic/tecla: cumple la regla; todo bien.
-
Si quisieras pre-cargar o reproducir “al cargar la página”, te toparás con bloqueos; usa preload="auto" y reproduce solo tras el primer input.
Ejemplo )
Finalmente debe de quedar algo como el siguiente ejemplo
Sound Board