Teclado: use keydown e keyup; keypress está deprecated. A propriedade event.key retorna o valor legível (“Enter”, “a”, “ArrowLeft”); event.code retorna a tecla física (“Enter”, “KeyA”) — independe do layout do teclado. Ponteiro: Pointer Events (pointerdown/pointermove/pointerup) unificam mouse, touch e stylus — prefira-os sobre eventos de mouse e touch separados. click borbulha e funciona para mouse e touch.
Eventos de teclado
A família de eventos de teclado
Evento
Quando
Deprecated?
keydown
Tecla pressionada — repete se mantida
Não
keyup
Tecla solta
Não
keypress
Tecla pressionada (só caracteres imprimíveis)
✅ Sim
Sempre use keydown — captura todas as teclas (incluindo Escape, Delete, setas) e é o padrão moderno. keyup é útil quando você quer aguardar a soltura (ex: finalizar arraste).
event.key: o que a tecla produz — depende do layout e do shift:
Pressionar a sem shift → "a"
Pressionar a com shift → "A"
Em teclado AZERTY (francês), onde a está em q → "a" também
event.code: a posição física da tecla — independente do layout:
A tecla física A sempre retorna "KeyA", mesmo em layout AZERTY
Útil para atalhos de jogo (WASD → “KeyW”/“KeyA”/“KeyS”/“KeyD”)
// ✅ Para atalhos de texto e UI — use event.keydocument.addEventListener('keydown', (event) => { if (event.key === 'Escape') closeModal(); if (event.key === 'Enter') submitForm(); if (event.key === 'ArrowUp') navigateUp();});// ✅ Para controles de jogo / posição física — use event.codedocument.addEventListener('keydown', (event) => { if (event.code === 'KeyW') moveForward(); if (event.code === 'KeyA') moveLeft(); // Funciona mesmo em layout AZERTY onde a tecla QWERTY-W não produz 'w'});
Modificadores
document.addEventListener('keydown', (event) => { event.ctrlKey; // Ctrl pressionado event.altKey; // Alt/Option pressionado event.shiftKey; // Shift pressionado event.metaKey; // Cmd (Mac) / Win key // Atalho cross-platform: Ctrl+K no Windows/Linux, Cmd+K no Mac if ((event.ctrlKey || event.metaKey) && event.key === 'k') { event.preventDefault(); // previne comportamento padrão do browser openCommandPalette(); }});
Teclas especiais e event.key values
// Navegação'ArrowUp' | 'ArrowDown' | 'ArrowLeft' | 'ArrowRight''Home' | 'End' | 'PageUp' | 'PageDown'// Edição'Backspace' | 'Delete' | 'Insert''Tab' | 'Enter'// UI'Escape' | 'Space' | 'F1'-'F12''CapsLock' | 'NumLock' | 'ScrollLock'// Modificadores sozinhos'Control' | 'Alt' | 'Shift' | 'Meta'// event.repeat: true se a tecla está sendo mantidadocument.addEventListener('keydown', (event) => { if (event.repeat) return; // ignora repetição de keydown});
Eventos de ponteiro
Pointer Events — a API unificada
Pointer Events unificam mouse, touch e stylus em uma única API:
element.addEventListener('pointerdown', (event) => { event.pointerId; // ID único (para rastrear multi-touch) event.pointerType; // "mouse" | "touch" | "pen" event.isPrimary; // true para o primeiro toque (multi-touch) event.pressure; // 0-1 (útil para stylus) event.clientX; // posição event.clientY; event.width; // área de contato (touch) event.height;});
Evento
Quando
pointerdown
Início do toque/clique
pointermove
Movimento com botão pressionado ou dedo movendo
pointerup
Soltar
pointercancel
Touch cancelado (ligação recebida, scroll, etc.)
pointerenter
Entrada no elemento (não borbulha)
pointerleave
Saída do elemento (não borbulha)
pointerover
Entrada no elemento ou filho (borbulha)
pointerout
Saída (borbulha)
click — o evento de ação
click funciona para mouse E touch, borbulha, e é o evento correto para ações de UI:
btn.addEventListener('click', handleAction);// Dispara em mouse click E tap mobile — não use pointerdown para ações de UI// ✅ Preferido para botões, links, cards clicáveis
Quando você chama element.setPointerCapture(pointerId), todos os eventos daquele ponteiro são entregues ao elemento, mesmo que o ponteiro saia dos seus limites. Essencial para drag-and-drop — sem isso, rápidos movimentos do mouse saem do elemento e o drag para.
// mouseenter: dispara só ao entrar no PRÓPRIO elemento (não borbulha)parent.addEventListener('mouseenter', () => { console.log('entrou no parent');});// Mover de parent → child: NÃO dispara novamente (mouseenter não borbulha de child)// mouseover: dispara ao entrar no elemento OU em qualquer filhoparent.addEventListener('mouseover', (event) => { console.log('mouseover em:', event.target);});// Mover de parent → child: dispara com target = child (borbulhou do child para parent)
Wheel e scroll
// wheel: evento da roda do mouse/trackpad (não o scroll em si)element.addEventListener('wheel', (event) => { event.deltaX; // scroll horizontal event.deltaY; // scroll vertical (positivo = para baixo) event.deltaZ; // scroll de profundidade (raro) event.deltaMode; // 0=pixels, 1=linhas, 2=páginas event.preventDefault(); // bloqueia o scroll nativo (útil para zoom customizado)}, { passive: false }); // passive:false necessário para poder chamar preventDefault// scroll: dispara quando o elemento JÁ scrollouwindow.addEventListener('scroll', (event) => { window.scrollY; // pixels scrollados verticalmente window.scrollX;});
passive: true e performance de scroll
Por padrão, o browser precisa aguardar o handler de wheel/touch para saber se você vai chamar preventDefault(). Isso adiciona latência ao scroll. Se você não vai chamar preventDefault(), declare { passive: true } — o browser pode fazer o scroll imediatamente:
// ✅ Para handlers de scroll que não bloqueiam o comportamento padrãodocument.addEventListener('wheel', handler, { passive: true });
Declarar passive: true e depois chamar preventDefault() lança um aviso no console e o preventDefault é ignorado.
Para fixar
Por que keypress está deprecated? Qual evento usar no lugar?
Qual a diferença entre event.key === 'a' e event.code === 'KeyA'? Dê um exemplo de quando a diferença importa.
O que setPointerCapture faz? Por que é essencial para drag-and-drop?
Por que mouseenter é preferido a mouseover para hover effects em um elemento com filhos?
O que significa um event listener ser passive? Qual o impacto de desabilitar o passive em handlers de scroll?