Wondering about keyboard events: What they are, when to use them, when to not use? Me too.

There’s a lot of information out there on browser-based keyboard events, but I couldn’t find practical advice to my questions in a single, coherent post so I thought I’d write some posts on the subject, starting with this one. I hope to provide you (and future me) with solid footing and helpful information. May our future selves spent less time debugging and more time making wonderful experiences for our users.

The first bit of practical advice I want to touch on is that keydown is likely the only keyboard event we need. The others, who needs them? Not us! Okay, maybe keyup goes on the shelf just in case, but surely keypress can be tossed out.

Why?

Let’s take a look starting with understanding what keyboard events exist today.

What are the keyboard events?

Here are the three keyboard events supported by all of the major browsers, in the order they are fired:

  • keydown – fires when any key is pressed down, fires first, and always before the browser processes the key (e.g. inserting text, moving focus, etc).
  • keypress – fires when a key that produces a character value is pressed down, fires after keydown, and before the browser processes the key.
  • keyup – fires when any key is released, fires last, and the browser processes the key.

Each of these events are cancelable and bubble up the DOM, but they’re not all equally useful.

Keydown is the only event you need to use

In my experience, keydown is the only keyboard event worth using, keypress can be ignored entirely, and keyup is well suited for getting dusty on the shelf.

Why?

Let’s take a look.

Reasons for using keydown

Key coverage

Keydown fires for any key so it’s going to give you the most coverage of keys being pressed. For example, it will fire for a character producing key like “f”, a modifier key like “Shift”, function keys, etc. You’ll never miss a keyboard event for a key that is pressed with keydown.

Cancelable

Another reason for keydown is that it fires before the browser processes the key so you have the opportunity to cancel it and/or stop it from bubbling up thru the DOM. If you don’t want to allow the letter “f” to be inserted – no problem – just cancel it using the event’s preventDefault method. If you don’t want the event to propagate out (aka bubble up thru the DOM) then you can stop that by using the event’s stopPropagation method.

Consistent across browsers

Another reason for using keydown is that it fires consistently across browsers. This is important because as you’ll see soon this isn’t always the case for its closely related event: keypress.

Speaking of keypress, let’s look at why we want to avoid keypress next.

Reasons for avoiding keypress

Lacks key coverage

Keypress fires after keydown, but still before the browser processes the key (e.g. inserting a character, moving focusing, submitting a form, etc). You can cancel and stop bubbling of keypress events just like you can keydown events, but keypressonly fires for a subset of keys – keys that produce character values – whereas keydown fires on all of the keys. So modifier keys like Shift, Control, Alt/Meta, function keys, etc won’t fire keypress events.

This can put you in a situation where you’re needlessly debugging keypress for not firing events or where you’re managing both keypress and keydown events. Why have two methods of capturing key events when one will do? Just use keydown.

Inconsistent across browsers

If you’re still not convinced here’s another reason to avoid keypress: It’s not fired consistently across browsers. What?! It’s mind boggling I know, but Firefox will fire a keypress event when Tab or any of the arrow keys are pressed , but no other browser will do this. Not Safari. Not Chrome. Not Opera. Not even IE.

Deprecated

A big reason to avoid keypress, and maybe I should have led with this, is that keypress is deprecated in the current W3C UI Events specification:

The keypress event type is defined in this specification for reference and completeness, but this specification deprecates the use of this event type.

The W3C specifications are sometimes a little ahead and sometimes a little behind browser implementation so somewhere down the road this may mean that browsers will do away with keypress. It’s not likely anytime soon though. It’s usage is too prevalent in web sites and applications that have been built between the mid-nineties and now. But, it is a good indicator that we should all stop using it moving forward.

RIP keypress.

With keypress out of way let’s move onto why keyup is best left to the sit on the shelf, collecting dust.

Reasons for shelving keyup

Let’s face it: keyup is fairly meaningless.

Keyboard events, keydown and keyup, are independent from each other. In fact, they sandwich the browser performing the action that the user would see (e.g. inserting text, deleting text, focusing the next focusable element, etc.)

No default action

If you cancel a keydown event it will prevent the browser from performing that action. But, it will not prevent keyup from firing when the key is lifted. Keyup is its own event. Now, just like keydown you can also cancel keyup, but it’s pointless. There is no default action associated with keyup. The only time you’d need to cancel it is if there was custom keyup handlers you wanted to prevent from being called.

Unless you really want to know that the user has lifted their finger from the key they have pressed – real or simulated – keyup really doesn’t have much to offer. A fine dust collector it makes.

And in the off chance you find a need for it, it’s right there, waiting to be used.

Avoid mixing keydown and keypress

Keyboard events are independent events except when they’re not. And with keydown and keypress they’re not. Eleven times out of ten this makes mixing and matching keyboard events unnecessarily complicated.

If you’re thinking of using both keydown and keypress I want to give you a word of discouragement: Don’t. If you are currently using them then the next time you’re in that code consider moving the keypress code over to akeydown event handler, and then promptly deleting the keypress handler.

Not only is the use ofkeypressportentous given that it’s deprecated, it also creates more work for you. Anything you can do with keypress you can do with keydown. It’s much simpler to have only one type of event to worry about. This mitigates complication caused by things like browsers inconsistently firing keypress and having to account for this in application code.

And you shouldn’t really even be using keypress. You read the above section – Reasons for not using keyup – right? Let keypress fall into the obscurity of history.

Keydown and keyup support complex interactions

One nice thing about the keydown and keyup that is not present with keypress is the ability to support more complex interactions between the application and the user. If you’re a Slack user you likely have pressed Ctrl-/ or Cmd-/ to toggle the shortcut panel. Side note: Slack is packaged as a native app, but it’s really an browser-based app served inside of an Electron wrapper.

In reviewing this post my colleague Ben Beckwith brought this up in some feedback. He even shared a simple example to illustrate this point:

Say you want functionality like the Slack shortcut panel. You want a user to be able to press Cmd-/ to toggle a pop-up box that showcases the available shortcuts to use in the application. In this situation keypress wouldn’t be relevant so you’d need to use eitherkeydown or keyup.

This example, as contrived as it may be, is a really great example for the usefulness of keydown and keyup. As for keypress, it gets another nail in the coffin.

Carry on keydown

If you’ve read this post then hopefully you’ve came to the same conclusion: keydown is a keeper, keypress is be tossed out, and keyup goes on the shelf. If you’re not convinced (or re-affirmed), don’t hesitate to tweet at me. I’m always up for incorporating new perspectives and information into my own thinking.

And if you’re looking for more information on using these events, their APIs, and their nitty gritty specification details here are a few handy references:

Here are a few links to the Mozilla Developer Network:

In follow-up posts we’ll take a look at jumping cursors and the prevalent return false statement that shows up in so many event handlers.

Until then, happy coding!

Would you like to know if custom software is right for you?