Eventos keydown e keyup do JavaScript
Aprenda eventos de teclado em JavaScript: como keydown e keyup diferem, o objeto KeyboardEvent (key vs code, modificadores, repeat) e exemplos práticos de atalhos, controles de jogos e navegação acessível.
Introdução aos Eventos de Teclado em JavaScript
Os eventos de teclado do JavaScript permitem que sua página reaja no momento em que o usuário pressiona ou solta uma tecla. Eles são a base de campos de busca em tempo real, atalhos de teclado, controles de jogos e navegação acessível. Este capítulo foca nos dois eventos mais utilizados — keydown e keyup — explica como eles diferem, percorre o objeto KeyboardEvent que cada manipulador recebe e termina com exemplos práticos e executáveis.
Se você ainda não tem experiência com manipulação de eventos em geral, comece por Introdução aos Eventos do Navegador e Manipulação de Eventos no DOM primeiro.
keydown vs. keyup em Resumo
Ambos os eventos disparam no elemento que tem o foco no momento (ou em document se nenhum elemento específico estiver focado). A diferença está em quando no ciclo de vida da tecla eles disparam:
| Evento | Dispara quando… | Repete enquanto pressionado? | Uso típico |
|---|---|---|---|
keydown | Uma tecla é pressionada | Sim — repetidamente | Atalhos, movimentos em jogos, bloqueio de entrada |
keyup | Uma tecla é solta | Não — uma vez por pressionamento | Detectar o fim de um pressionamento, finalizar a UI |
Um toque simples em uma tecla produz um keydown seguido de um keyup. Manter uma tecla pressionada dispara keydown repetidamente (é possível detectar essas repetições automáticas com event.repeat), mas keyup só dispara uma vez, quando você finalmente solta a tecla.
O evento legado
keypressestá obsoleto e não deve ser usado em código novo. Para reagir ao texto digitado pelo usuário, use o eventoinput.
Entendendo keydown e keyup
O Evento keydown
O evento keydown ocorre quando o usuário pressiona uma tecla no teclado. Ele dispara antes de o caractere ser inserido em um campo, e é exatamente por isso que é o lugar certo para chamar event.preventDefault() quando você deseja bloquear a entrada. Esse evento é útil sempre que o momento do pressionamento importa — jogos, recursos de acessibilidade ou controles interativos.
Exemplo do 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>O código escuta o evento keydown no campo de entrada e verifica se a tecla pressionada é "Enter". Se for, altera a cor de fundo do campo para amarelo (classe highlight) e impede a submissão padrão do formulário ou outras ações normalmente associadas à tecla Enter.
O Evento keyup
O evento keyup é acionado quando uma tecla é solta, após o evento keydown (observação: o evento legado keypress está obsoleto e raramente usado no desenvolvimento web moderno). Esse evento é adequado para casos em que você precisa saber quando um pressionamento de tecla foi concluído, como ao atualizar uma interface de usuário ou controlar conteúdo multimídia.
Exemplo do 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 faz a área de texto mudar sua cor de fundo para verde claro (classe active) quando a tecla Control é pressionada e retorna ao transparente (classe normal) quando a tecla Control é solta.
O Objeto KeyboardEvent
Cada manipulador de keydown e keyup recebe um KeyboardEvent. Conhecer suas principais propriedades é o que permite escrever lógica de teclado confiável.
key vs. code
Essas duas propriedades são fáceis de confundir, e escolher a errada é a fonte mais comum de bugs de teclado:
event.key— o caractere ou valor nomeado produzido, respeitando o layout do teclado e os modificadores. Pressionar a teclaAretorna"a", ou"A"com Shift pressionado. Teclas com nome:"Enter","Escape","ArrowLeft"," "(espaço).event.code— a tecla física no teclado, independente do layout ou dos modificadores. A mesma tecla física é sempre"KeyA", independentemente de o usuário digitara,Aou ter um layout não-QWERTY.
Use key quando você se importa com o caractere (entrada de texto, atalhos descritos para o usuário). Use code quando você se importa com a posição — por exemplo, controles WASD em jogos que devem funcionar independentemente do layout.
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 e repeat
O evento também informa quais teclas modificadoras estão pressionadas e se o pressionamento é uma repetição automática do sistema operacional:
event.altKey,event.ctrlKey,event.shiftKey,event.metaKey— booleanos,trueenquanto aquele modificador estiver pressionado. (metaKeyé Cmd no macOS, a tecla Windows em outros sistemas.)event.repeat—truequando uma tecla mantida pressionada disparakeydownnovamente automaticamente. Verifique-o para ignorar repetições 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');
}
});Ler os flags de modificador diretamente (como acima) é mais robusto do que rastrear uma variável separada ctrlPressed, pois os flags têm garantia de estar sincronizados com a realidade mesmo que você perca um keyup.
Usos Avançados de Eventos de Teclado em JavaScript
Usar o poder de eventos de teclado como keydown e keyup pode transformar aplicações web comuns em plataformas altamente interativas, acessíveis e eficientes. Aqui, expandimos seus usos incorporando-os em cenários mais complexos, como atalhos personalizados, controles de jogos e recursos de acessibilidade.
Implementando Hotkeys Personalizados
Hotkeys personalizados permitem que os usuários realizem ações rapidamente, aumentando a produtividade e a experiência do usuário. Este exemplo demonstra como criar um hotkey personalizado simples (Ctrl + S) para simular uma ação de salvar, que pode ser adaptada para acionar funcionalidades específicas em aplicações reais.
Exemplo de Hotkeys 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>Manipulando Controles de Jogos
Os controles de jogos são essenciais para jogos baseados em navegador. Este exemplo fornece uma implementação simples de controles com as teclas de seta para mover um objeto de jogador dentro de uma área de jogo, oferecendo uma estrutura básica que pode ser expandida para mecânicas de jogo mais complexas.
Exemplo de Controles de Jogo
<!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>Melhorando a Acessibilidade
As melhorias de acessibilidade ajudam a tornar as aplicações web utilizáveis por pessoas com deficiências. Este exemplo foca no uso de eventos keydown para navegar entre links usando as teclas de seta do teclado, facilitando a navegação por teclado para usuários que não podem usar um mouse.
Exemplo de Melhoria de Acessibilidade
<!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>Esses exemplos não apenas ilustram a implementação técnica dos eventos keydown e keyup, mas também demonstram suas aplicações práticas para melhorar a interatividade e a acessibilidade das aplicações web. Ao incorporar essas funcionalidades avançadas, os desenvolvedores podem criar experiências de usuário mais envolventes e inclusivas.
Conclusão
Eventos de teclado como keydown e keyup são indispensáveis para criar aplicações web dinâmicas e interativas. Lembre-se dos pontos essenciais: keydown dispara (e se repete) no pressionamento, keyup dispara uma vez na soltura, event.key fornece o caractere enquanto event.code fornece a tecla física, e os flags de modificador junto com event.repeat permitem criar atalhos robustos. Os exemplos acima são um ponto de partida para adicionar interação por teclado aos seus próprios projetos.
Capítulos Relacionados
- Introdução aos Eventos do Navegador — como os eventos funcionam em alto nível.
- Manipulação de Eventos no DOM —
addEventListener, manipuladores e remoção. - Eventos: change, input, cut, copy, paste — reagir ao texto que realmente chega a um campo.
- Foco: focus e blur — combina naturalmente com a navegação por teclado.
- Bubbling e Capturing — como os eventos de teclado se propagam pelo DOM.