JavaScript Keyboard Events: key vs code vs keyCode Explained
JavaScript Keyboard Events: key vs code vs keyCode Explained#
I was building a keyboard shortcut feature recently and kept mixing up event.key, event.code, and event.keyCode. So I built an online tool to test them, and here’s what I learned.
A Quick Comparison#
Press the “A” key:
document.addEventListener('keydown', (e) => {
console.log(e.key) // "a" (lowercase, no Shift)
console.log(e.code) // "KeyA"
console.log(e.keyCode) // 65
})
Now press Shift + A:
e.key // "A" (uppercase)
e.code // "KeyA" (unchanged)
e.keyCode // 65 (also unchanged)
See the difference?
- key: The character value of the key, affected by Shift and CapsLock
- code: The physical position of the key, regardless of Shift
- keyCode: The numeric code of the key (deprecated but still works)
key vs code: Which to Use?#
Use key for: Text Input#
When you care about what character the user typed:
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
submitForm()
}
if (e.key === 'Escape') {
closeModal()
}
})
Use code for: Shortcuts, Game Controls#
When you care about which physical key was pressed:
// Game controls: WASD movement
document.addEventListener('keydown', (e) => {
switch (e.code) {
case 'KeyW': moveForward(); break
case 'KeyA': moveLeft(); break
case 'KeyS': moveBackward(); break
case 'KeyD': moveRight(); break
}
})
Why use code for games? Users might switch keyboard layouts (Dvorak, Colemak). key changes, but the physical position code stays the same.
keyCode: Deprecated but Not Dead#
keyCode is marked deprecated in the spec, but:
- Lots of legacy code still uses it
- Sometimes it’s more convenient than
key(number comparison vs string comparison)
// Old way (deprecated)
if (e.keyCode === 13) { /* Enter */ }
// New way
if (e.key === 'Enter') { /* ... */ }
location: Distinguishing Left/Right Shift, Alt, Ctrl#
The same key in different positions has different location values:
document.addEventListener('keydown', (e) => {
console.log(e.location)
// 0 = Standard position
// 1 = Left side
// 2 = Right side
// 3 = Numpad
})
Left Shift → location: 1, Right Shift → location: 2.
Useful for fine-grained shortcuts, like Photoshop’s “right Alt as tool switcher”.
Modifier States: ctrlKey, shiftKey, altKey, metaKey#
Check modifier keys directly with boolean properties:
document.addEventListener('keydown', (e) => {
// Ctrl + S to save
if (e.ctrlKey && e.key === 's') {
e.preventDefault()
saveDocument()
}
// Cmd + S (Mac)
if (e.metaKey && e.key === 's') {
e.preventDefault()
saveDocument()
}
})
Note: On Mac, metaKey is the Command key. On Windows, it’s the Windows key.
repeat: Detecting Key Hold#
Holding a key triggers multiple keydown events. Starting from the second one, e.repeat is true:
document.addEventListener('keydown', (e) => {
if (e.repeat) {
console.log('User is holding this key')
}
})
Useful for games to implement “hold to continuous fire”.
Practical Example: A Shortcut Handler#
interface Shortcut {
key: string
ctrl?: boolean
shift?: boolean
alt?: boolean
meta?: boolean
action: () => void
}
function createShortcutHandler(shortcuts: Shortcut[]) {
document.addEventListener('keydown', (e) => {
for (const shortcut of shortcuts) {
const ctrlMatch = shortcut.ctrl ? e.ctrlKey : !e.ctrlKey
const shiftMatch = shortcut.shift ? e.shiftKey : !e.shiftKey
const altMatch = shortcut.alt ? e.altKey : !e.altKey
const metaMatch = shortcut.meta ? e.metaKey : !e.metaKey
if (
e.key === shortcut.key &&
ctrlMatch &&
shiftMatch &&
altMatch &&
metaMatch
) {
e.preventDefault()
shortcut.action()
break
}
}
})
}
// Usage
createShortcutHandler([
{ key: 's', ctrl: true, action: saveDocument },
{ key: 'z', ctrl: true, action: undo },
{ key: 'z', ctrl: true, shift: true, action: redo },
])
Common Pitfalls#
1. Case Sensitivity#
e.key is case-sensitive. Press A without Shift, e.key is 'a', not 'A'.
// Wrong
if (e.key === 'A') { /* Never triggers */ }
// Correct
if (e.key.toLowerCase() === 'a') { /* ... */ }
2. Special Key Values#
Special keys have non-single-character key values:
'Enter', 'Escape', 'Backspace', 'Tab', 'Space'
'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'
'Control', 'Shift', 'Alt', 'Meta'
Note: The spacebar’s key can be ' ' or 'Space' (browser-dependent).
3. Dead Keys#
When an IME is active, some keys may trigger keydown but e.key is 'Dead'. This matters for international keyboard handling.
Online Testing Tool#
For easier debugging, I built: Keyboard Key Detector
Features:
- Real-time display of key, code, keyCode, which
- Visual modifier key states
- location position info
- History (last 10 keys)
Very handy when building shortcut features—just press and see all property values.
Related: Keyboard Test | Shortcut Generator