Here’s how to listen to more complex keyboard input with JavaScript.
A basic example
Usually, it’s better to listen keyup, because with keydown it’s easy to
unleash a deluge of events possibly bogging up your site.
const handleKeyboard = event => {
if (event.key === '/') console.log('The ’/’ key was pressed')
}
document.addEventListener('keyup', handleKeyboard)Anatomy of the KeyboardEvent
This is roughly what the event contains when an alt key was pressed:
{
altKey: false,
ctrlKey: false,
metaKey: false,
shiftKey: false,
charCode: 0,
code: "AltLeft",
isComposing: false,
key: "Alt",
keyCode: 18,
location: 1,
repeat: false,
type: "keyup",
which: 18,
// Unrelated properties redacted for brevity.
}Here’s a quick rundown what each of them do:
KeyboardEvent.altKeyA boolean telling you if an alt key was pressed when the event was initiated.
KeyboardEvent.ctrlKeyA boolean telling you if an ctrl key was pressed when the event was initiated.
KeyboardEvent.metaKeyA boolean telling you if a Meta key was pressed when the event was initiated. In Mac this would be ⌘ Command and in Windows it would be the ⊞ Windows key.
KeyboardEvent.shiftKeyA boolean telling you if a shift key was pressed when the event was initiated.
KeyboardEvent.charCode👎Deprecated, but it returns the Unicode value of the character pressed.
KeyboardEvent.codeReturns the name of a physical key on the keyboard, not the character generated by pressing a key, meaning it’s immune to keyboard layouts or modifier keys. You can get really granular with this, for example you can know which alt key was pressed for example
AltLeftorAltRightKeyboardEvent.isComposingA boolean value indicating whether the event was fired during an open compositions session e.g: between
compositionstartandcompositionend. Composition session is when a character is required to be entered using multiple keystrokes, like Chinese characters or accented characters like "à": alt+` followed by an a.KeyboardEvent.keyReturns the name of the key pressed, including the state of any modifier keys.
KeyboardEvent.keyCode👎Deprecated, but it’s still widely used (as of writing this). It returns the numerical value of of the key.
KeyboardEvent.locationThe location can have 4 values: 0, 1, 2, and 3. The location is 0 if a key has only one version (i.e. "g"), 1 if it was the left-hand version of a key (like alt), 2 if right-hand side, and 3 if the key is part of a numeric keypad.
KeyboardEvent.repeatA boolean property signaling whether the key is pressed in during a
keydownevent.KeyboardEvent.shiftKeyA boolean telling if a shift key was pressed when the event was initiated.
KeyboardEvent.typeNot purely a keyboard event property. A string value simply representing the event name. Handy when listening to multiple events at the same time.
Listening key combos: Cmd or Ctrl + key
I’m using Cmd+/ (or Ctrl+/) as an example here (which
opens the search on this site btw). When doing key-combos it’s good to listen to
the keydown event:
const handleKeyboard = ({ repeat, metaKey, key }) => {
if (repeat) return
if ((metaKey || ctrlKey) && key === '/') console.log('’Cmd+/’ was pressed')
}
document.addEventListener('keydown', handleKeyboard)See the bail on the repeat, without that, there would be a torrential flood of
events firing when the key is kept in a pressed state, which might bog up your
app.
Key-combo example using React
This little demo toggles a search bar on the header with Cmd+/ or
Ctrl+/:
const [searchOpen, setSearchOpen] = React.useState(false)
const handleKeyboard = ({ repeat, metaKey, ctrlKey, key }) => {
if (repeat) return
// Handle both, `ctrl` and `meta`.
if ((metaKey || ctrlKey) && key === '/') setSearchOpen(prev => !prev)
}
React.useEffect(() => {
document.addEventListener('keydown', handleKeyboard)
// Important to remove the listeners.
return () => document.removeEventListener('keydown', handleKeyboard)
})Notes on the above code:
- Remember to handle both
metaKeyandctrlKeyso it works on Windows and Mac. - Also remove the events when you’re done with them: using function components
you return a function and run the cleanup inside that. It’s equivalent to the
good old
componentWillUnmountmethod.
Listening to multiple keys that are not meta, ctrl, or alt
If you want to, say, open the search when s and e are
pressed, you need to be a bit more clever. You can keep a log of the keys
pressed on keydown and then clear the log on keyup:
const keyLog = {}
const handleKeyboard = ({ type, key, repeat, metaKey }) => {
if (repeat) return
if (type === 'keydown') {
keyLog[key] = true
// When "s" and "e" are pressed.
if (keyLog.s && key === 'e') setSearchOpen(prev => !prev)
}
// Remove the key from the log on keyup.
if (type === 'keyup') delete keyLog[key]
}
React.useEffect(() => {
const events = ['keydown', 'keyup']
events.forEach(name => document.addEventListener(name, handleKeyboard))
return () =>
events.forEach(name => document.removeEventListener(name, handleKeyboard))
})Here’s a demo for that one: