Eventos keydown y keyup de JavaScript
Aprende los eventos de teclado en JavaScript: diferencias entre keydown y keyup, el objeto KeyboardEvent (key vs code, modificadores, repeat) y ejemplos prácticos de atajos, controles de juego y navegación accesible.
Introducción a los eventos de teclado en JavaScript
Los eventos de teclado de JavaScript permiten que tu página reaccione en el momento en que el usuario presiona o suelta una tecla. Son la base de los campos de búsqueda en tiempo real, los atajos de teclado, los controles de juegos y la navegación accesible. Este capítulo se centra en los dos eventos que usarás con mayor frecuencia — keydown y keyup — explica sus diferencias, recorre el objeto KeyboardEvent que recibe cada manejador y finaliza con ejemplos prácticos y ejecutables.
Si eres nuevo en el manejo de eventos en general, comienza primero con Introducción a los eventos del navegador y Manejo de eventos en el DOM.
keydown vs. keyup de un vistazo
Ambos eventos se disparan en el elemento que tiene el foco en ese momento (o en document si no hay nada específico enfocado). La diferencia está en cuándo dentro del ciclo de vida de la tecla se disparan:
| Evento | Se dispara cuando… | ¿Se repite al mantener? | Uso típico |
|---|---|---|---|
keydown | Se presiona una tecla | Sí — repetidamente | Atajos, movimiento en juegos, bloqueo de entrada |
keyup | Se suelta una tecla | No — una vez por pulsación | Detectar cuando termina la pulsación, finalizar la UI |
Una pulsación simple de una tecla produce un keydown y luego un keyup. Mantener una tecla presionada dispara keydown una y otra vez (puedes detectar estas repeticiones automáticas con event.repeat), pero keyup solo se dispara una vez, cuando finalmente la sueltas.
El evento heredado
keypressestá obsoleto y no debe usarse en código nuevo. Para reaccionar al texto que escribe el usuario, escucha el eventoinputen su lugar.
Comprendiendo keydown y keyup
El evento keydown
El evento keydown ocurre cuando el usuario presiona una tecla del teclado. Se dispara antes de que el carácter se inserte en un campo, lo cual es exactamente por qué es el lugar correcto para llamar a event.preventDefault() cuando quieres bloquear la entrada. Este evento es útil cuando importa el momento exacto de la pulsación — juegos, características de accesibilidad o controles interactivos.
Ejemplo del evento keydown
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Example of Keydown Event</title>
<style>
.highlight { background-color: yellow; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const inputField = document.getElementById('inputField');
inputField.addEventListener('keydown', function(event) {
console.log('Key down:', event.key);
if (event.key === "Enter") {
this.classList.add('highlight');
event.preventDefault(); // Prevents the default action of the enter key
}
});
});
</script>
</head>
<body>
<input type="text" id="inputField" placeholder="Press 'Enter' to highlight" />
</body>
</html>El código escucha un evento keydown en el campo de entrada y comprueba si la tecla presionada es "Enter". Si es así, cambia el color de fondo del campo de entrada a amarillo (clase highlight) e impide el envío predeterminado del formulario u otras acciones típicamente asociadas a la tecla Enter.
El evento keyup
El evento keyup se activa cuando se suelta una tecla, después del evento keydown (nota: el evento heredado keypress está obsoleto y rara vez se usa en el desarrollo web moderno). Este evento es adecuado para los casos en que necesitas saber cuándo ha concluido la pulsación de una tecla, como al actualizar una interfaz de usuario o controlar contenido multimedia.
Ejemplo del evento keyup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Example of Keyup Event</title>
<style>
.normal { background-color: transparent; }
.active { background-color: lightgreen; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const textArea = document.getElementById('textArea');
textArea.addEventListener('keyup', function(event) {
console.log('Key up:', event.key);
if (event.key === "Control") {
this.classList.remove('active');
this.classList.add('normal');
}
});
textArea.addEventListener('keydown', function(event) {
if (event.key === "Control") {
this.classList.add('active');
}
});
});
</script>
</head>
<body>
<textarea id="textArea" rows="4" cols="50" placeholder="Press and release 'Control' to see the effect"></textarea>
</body>
</html>Este código hace que el área de texto cambie su color de fondo a verde claro (clase active) cuando se presiona la tecla Control y lo devuelve a transparente (clase normal) cuando se suelta.
El objeto KeyboardEvent
Cada manejador de keydown y keyup recibe un KeyboardEvent. Conocer sus propiedades clave es lo que te permite escribir lógica de teclado fiable.
key vs. code
Estas dos propiedades son fáciles de confundir, y elegir la incorrecta es la fuente más común de errores relacionados con el teclado:
event.key— el carácter o valor con nombre producido, respetando la distribución del teclado y los modificadores. Presionar la teclaAda"a", o"A"con Shift. Nombres de teclas:"Enter","Escape","ArrowLeft"," "(espacio).event.code— la tecla física del teclado, independiente de la distribución o los modificadores. La misma tecla física siempre es"KeyA"sin importar si el usuario escribea,A, o tiene una distribución que no es QWERTY.
Usa key cuando te importe el carácter (entrada de texto, atajos indicados al usuario). Usa code cuando te importe la posición — por ejemplo, los controles WASD en juegos que deben funcionar independientemente de la distribución.
document.addEventListener('keydown', function (event) {
console.log(event.key, event.code);
});
// Pressing Shift+A on QWERTY logs: "A" "KeyA"
// Pressing the space bar logs: " " "Space"Teclas modificadoras y repetición
El evento también informa qué teclas modificadoras están presionadas y si la pulsación es una repetición automática del sistema operativo:
event.altKey,event.ctrlKey,event.shiftKey,event.metaKey— valores boolean,truemientras ese modificador está presionado. (metaKeyes Cmd en macOS, la tecla Windows en otros sistemas.)event.repeat—truecuando una tecla mantenida presionada disparakeydownnuevamente de forma automática. Compruébalo para ignorar las repeticiones automáticas.
document.addEventListener('keydown', function (event) {
// Cross-platform "save" shortcut, ignoring auto-repeat.
if ((event.ctrlKey || event.metaKey) && event.key === 's' && !event.repeat) {
event.preventDefault();
console.log('Save triggered');
}
});Leer los indicadores de modificadores directamente (como se muestra arriba) es más robusto que rastrear una variable separada ctrlPressed, porque los indicadores están garantizados a estar sincronizados con la realidad incluso si te pierdes un keyup.
Usos avanzados de los eventos de teclado en JavaScript
Aprovechar el poder de los eventos de teclado como keydown y keyup puede transformar las aplicaciones web ordinarias en plataformas altamente interactivas, accesibles y eficientes. Aquí ampliamos sus usos incorporándolos en escenarios más complejos como atajos personalizados, controles de juego y características de accesibilidad.
Implementación de atajos personalizados
Los atajos personalizados permiten a los usuarios realizar acciones rápidamente, mejorando la productividad y la experiencia del usuario. Este ejemplo demuestra cómo crear un atajo personalizado simple (Ctrl + S) para simular una acción de guardar, que podría adaptarse para activar funcionalidades específicas en aplicaciones reales.
Ejemplo de atajos personalizados
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Custom Hotkeys Example</title>
<script>
document.addEventListener('DOMContentLoaded', function () {
let ctrlPressed = false;
document.addEventListener('keydown', function(event) {
if (event.key === "Control") {
ctrlPressed = true;
}
// Use toLowerCase() for case-insensitive matching
if (event.key.toLowerCase() === "s" && ctrlPressed) {
alert('Saving your progress!');
event.preventDefault(); // Prevent default to stop other actions like browser shortcuts
}
});
document.addEventListener('keyup', function(event) {
if (event.key === "Control") {
ctrlPressed = false;
}
});
});
</script>
</head>
<body>
<p>Press <strong>Ctrl + S</strong> to simulate a save action.</p>
</body>
</html>Manejo de controles de juego
Los controles de juego son fundamentales para los juegos basados en navegador. Este ejemplo proporciona una implementación simple de controles con teclas de flecha para mover un objeto jugador dentro de un área de juego, ofreciendo un marco básico que puede ampliarse hacia mecánicas de juego más complejas.
Ejemplo de controles de juego
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Game Control Example</title>
<style>
#gameArea {
width: 300px;
height: 300px;
border: 1px solid black;
position: relative;
}
#player {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
top: 125px;
left: 125px;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const player = document.getElementById('player');
// Note: offsetLeft/Top don't account for container padding or scroll offsets.
// For production, consider using getBoundingClientRect() or adding padding offsets.
let posX = player.offsetLeft;
let posY = player.offsetTop;
document.addEventListener('keydown', function(event) {
switch (event.key) {
case "ArrowUp":
posY -= 10;
break;
case "ArrowDown":
posY += 10;
break;
case "ArrowLeft":
posX -= 10;
break;
case "ArrowRight":
posX += 10;
break;
}
player.style.left = posX + 'px';
player.style.top = posY + 'px';
});
});
</script>
</head>
<body>
<div id="gameArea">
<div id="player"></div>
</div>
<p>Use arrow keys to move the red square within the game area.</p>
</body>
</html>Mejora de la accesibilidad
Las mejoras de accesibilidad ayudan a que las aplicaciones web sean utilizables por personas con discapacidades. Este ejemplo se centra en usar eventos keydown para navegar entre enlaces con las teclas de flecha del teclado, facilitando la navegación guiada por teclado para usuarios que no pueden usar un ratón.
Ejemplo de mejora de accesibilidad
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Accessibility Navigation Example</title>
<script>
document.addEventListener('DOMContentLoaded', function () {
const links = document.querySelectorAll('a');
let currentFocus = 0;
links[currentFocus].focus();
document.addEventListener('keydown', function(event) {
if (event.key === "ArrowDown") {
currentFocus = (currentFocus + 1) % links.length;
links[currentFocus].focus();
event.preventDefault();
}
if (event.key === "ArrowUp") {
currentFocus = (currentFocus - 1 + links.length) % links.length;
links[currentFocus].focus();
event.preventDefault();
}
});
});
</script>
</head>
<body>
<nav>
<a href="#home">Home</a>
<a href="#about">About</a>
<a href="#services">Services</a>
<a href="#contact">Contact</a>
</nav>
<p>Use the Up and Down arrow keys to navigate between the links.</p>
</body>
</html>Estos ejemplos no solo ilustran la implementación técnica de los eventos keydown y keyup, sino que también demuestran sus aplicaciones prácticas para mejorar la interactividad y la accesibilidad de las aplicaciones web. Al incorporar estas funcionalidades avanzadas, los desarrolladores pueden crear experiencias de usuario más atractivas e inclusivas.
Conclusión
Los eventos de teclado como keydown y keyup son indispensables para crear aplicaciones web dinámicas e interactivas. Recuerda los fundamentos: keydown se dispara (y se repite) al presionar, keyup se dispara una vez al soltar, event.key te da el carácter mientras que event.code te da la tecla física, y los indicadores de modificadores junto con event.repeat te permiten construir atajos robustos. Los ejemplos anteriores son un punto de partida para añadir interacción por teclado a tus propios proyectos.
Capítulos relacionados
- Introducción a los eventos del navegador — cómo funcionan los eventos a alto nivel.
- Manejo de eventos en el DOM —
addEventListener, manejadores y eliminación. - Eventos: change, input, cut, copy, paste — reacciona al texto que realmente llega a un campo.
- Enfoque: focus y blur — se complementa de forma natural con la navegación por teclado.
- Propagación y captura de eventos — cómo se propagan los eventos de teclado a través del DOM.