Keyboard events

By

Learn how to handle keyboard events in JavaScript with keydown and keyup on the document, and read the KeyboardEvent key, code, and modifier properties.

~~~

There are two keyboard events you’ll work with:

A third one, keypress, is obsolete. Browsers still fire it, but don’t use it in new code. When you care about the text typed into a field, use the input event instead (more on this below).

keydown is also fired when the key repeats while the button stays pressed.

While mouse and touch events are typically listened on a specific element, it’s common to listen for keyboard events on the document:

document.addEventListener('keydown', (event) => {
  // key pressed
})

The parameter passed to the event listener is a KeyboardEvent.

This event object, in addition to the Event object properties offers us (among others) these unique properties:

You can also call event.getModifierState('CapsLock') (and similar modifier names) when you need the lock state of a modifier key.

This demo is a keylogger which will show you the values of some of the properties I listed above: https://codepen.io/flaviocopes/pen/LopWmq/

key vs code

key is the character or action the user meant. code is the physical key they pressed.

On a US keyboard, the key labeled A gives you:

document.addEventListener('keydown', (event) => {
  console.log(event.key) // 'a' (or 'A' with Shift)
  console.log(event.code) // 'KeyA'
})

Press Enter and you get event.key === 'Enter' and event.code === 'Enter'. Press the left arrow and you get event.key === 'ArrowLeft' and event.code === 'ArrowLeft'.

Use key when you care about the meaning: save, submit, move left. Use code when you care about the physical position, like WASD controls that should stay on those keys even on a non-US layout.

Detecting a keyboard shortcut

The modifier properties let you detect shortcuts. A common pattern is Cmd+S on Mac and Ctrl+S elsewhere:

document.addEventListener('keydown', (event) => {
  const savePressed =
    (event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 's'

  if (!savePressed) {
    return
  }

  event.preventDefault()
  // save the document
})

metaKey is the Command key on Mac. ctrlKey is Control on Windows and Linux. Checking both covers both platforms. toLowerCase() keeps the check working when Shift or Caps Lock is on, since key is then 'S'.

When preventDefault matters

Browsers already react to some keys. Space scrolls the page. Enter submits a focused form. Ctrl/Cmd+S opens the browser save dialog.

Call event.preventDefault() when your handler should own that key and the default action would get in the way:

document.addEventListener('keydown', (event) => {
  if (event.key !== ' ') {
    return
  }

  event.preventDefault()
  // space triggers your action, the page does not scroll
})

Only cancel what you handle. Leave Tab, Escape, and browser shortcuts alone unless you have a real reason. For the broader difference between preventDefault and stopPropagation, see preventDefault vs stopPropagation.

Prefer the input event for text fields

keydown tells you a key was pressed. It does not tell you the field value after that key.

When the user is typing into an <input> or <textarea>, listen for input on that field. You get the updated value after every change, including paste and autofill:

const search = document.querySelector('#search')

search.addEventListener('input', (event) => {
  console.log(event.target.value)
})

Keep keydown for shortcuts and navigation. Use input when you care about the text itself. Form field events such as change, focus, and blur are covered in Handling forms in JavaScript.

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about platform: