275

According to MDN, we should most definitely not be using the .keyCode property. It is deprecated:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

On W3 school, this fact is played down and there is only a side note saying that .keyCode is provided for compatibility only and that the latest version of the DOM Events Specification recommend using the .key property instead.

The problem is that .key is not supported by browsers, so what should we using? Is there something I'm missing?

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
Jason210
  • 2,990
  • 2
  • 17
  • 18
  • 8
    `.key` is supported in every major browser https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#Browser_compatibility – sbolel Jun 18 '18 at 23:24
  • This question doesn't seem particularly useful anymore since all modern browsers support `event.key`. – Herohtar Aug 20 '22 at 04:16

9 Answers9

226

For instance if you want to detect whether the "Enter"-key was clicked or not:

Instead of

event.keyCode === 13

Do it like

event.key === 'Enter'
Thomas Gotwig
  • 3,659
  • 3
  • 17
  • 15
  • 8
    In the light of the "in practice" part of the question, this should be the accepted answer. – Eduardo Pignatelli Dec 26 '20 at 14:33
  • 3
    For non-ASCII composing letters, the key event fires twice. Each are { key: 'Enter', keyCode: 13 }, { key: 'Enter', keyCode: 229 }. How can I avoid second event without keyCode? – khcpietro Jul 22 '21 at 02:14
  • @khcpietro Can’t really reproduce that with `Enter`, but there’s an [`isComposing`](//developer.mozilla.org/docs/Web/API/KeyboardEvent/isComposing) property and two related events that may help. – Sebastian Simon Oct 25 '21 at 16:29
  • 4
    The list of all possible values of event.key: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values – Christopher K. Oct 29 '21 at 10:11
  • 5
    `event.keyCode === 27` become: `event.key === 'Escape'` – Gil Epshtain Feb 08 '22 at 13:37
  • 15
    keep in mind that changing from `event.keyCode === 13` to `event.key === 'Enter'` drops support for numpad keys. To support both, check both: `event.key === 'Enter' || event.key === 'NumpadEnter'` or better yet: `['Enter', 'NumpadEnter'].includes(event.key)` – Austin Arnett Mar 07 '22 at 15:22
  • 2 cents for the shortest code / widest test: `/enter/i.test(key)` – Josh Leslie Apr 18 '22 at 19:10
  • 1
    @AustinArnett `.key==="Enter"` for both keys. But `.code` can also be "NumpadEnter". – Winand May 12 '23 at 16:48
75

You have three ways to handle it, as it's written on the link you shared.

if (event.key !== undefined) {

} else if (event.keyIdentifier !== undefined) {

} else if (event.keyCode !== undefined) {

}

you should contemplate them, that's the right way if you want cross browser support.

It could be easier if you implement something like this.

var dispatchForCode = function(event, callback) {
  var code;

  if (event.key !== undefined) {
    code = event.key;
  } else if (event.keyIdentifier !== undefined) {
    code = event.keyIdentifier;
  } else if (event.keyCode !== undefined) {
    code = event.keyCode;
  }

  callback(code);
};
Federico Grandi
  • 6,785
  • 5
  • 30
  • 50
Miguel Lattuada
  • 5,327
  • 4
  • 31
  • 44
  • 24
    I did read that that but it seemed to be a lot of extra code for no other reason than MDN have said something is deprecated, when it actually works fine in all major browsers. But if that's the correct way then thanks! – Jason210 Feb 14 '16 at 18:14
  • 4
    Wow look a this. http://caniuse.com/#search=keyCode (This KeyboardEvent property is supported in effectively all browsers (since IE6+, Firefox 2+, Chrome 1+ etc "talking about .keyCode) – Miguel Lattuada Feb 14 '16 at 18:25
  • 6
    That's what is so annoying about all this. All major browsers support keyCode, but try do a check for the .key property, which is the recommended one, and hardly any use it! – Jason210 Feb 14 '16 at 18:32
  • 4
    Yeah, we're up to late May 2016, and chrome finally implemented the KeyboardEvent.key property. Safari along with every mobile browser has yet to join the "16.5% of all users" party. Also, sadly, Microsoft Edge and Gecko encode quite a few of the events differently for example: the key event for the up arrow is encoded as "Up" instead of "ArrowUp". – Joshua Dawson May 31 '16 at 05:05
  • I think this will help you https://stackoverflow.com/questions/41465542/angular2-input-field-to-accept-only-numbers – R0b1n Jan 21 '20 at 06:20
  • 6
    But `event.key` is a string, whereas `event.keyCode` is a number, right? Given that they don't even have the same type, have can they have the same semantics? Or do you mean `event.code`? – bluenote10 Dec 07 '20 at 14:06
  • 3
    As of now, all major browsers support `event.key` and `event.code` (check @kumarharsh's answer). It being a `string` also makes it a lot more readable, so I advise using it for all new code. For maintaining legacy, it will depend on how much you depend on it being a `number`. Just be aware that when you hit a printable key, `event.key` "a" and "A" are different while `event.code` will be "keyA" for both. For non printable, you can have `event.code` being "ShiftLeft" or "ShiftRight" while `event.key` will be "Shift" for both. – Guilherme Taffarel Bergamin Jan 25 '21 at 17:26
  • What is the benefit of using a callback for this function? – Koray Mar 29 '21 at 08:45
  • 1
    @GuilhermeTaffarelBergamin Sorry to burst your bubble but Chrome on Android still doesn't support event.code (as of June 2021). But I agree that the way to go is probably to use those (code and key) and to import a polyfill. Making things cross browser should not be mingled with your business code. – pieroxy Jun 20 '21 at 10:07
  • @pieroxy. I should probably test that again then to be sure, because [according to MDN](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code), `event.code` became available on Chrome for Android on version 48 with full support. But now that you mention it, [according to caniuse](https://caniuse.com/keyboardevent-code), it is only supported if turned it on as an experimental feature flag. – Guilherme Taffarel Bergamin Jun 21 '21 at 18:31
49

TLDR: I'd suggest that you should use the new event.key and event.code properties instead of the legacy ones. IE and Edge have support for these properties, but don't support the new key names yet. For them, there is a small polyfill which makes them output the standard key/code names:

https://github.com/shvaikalesh/shim-keyboard-event-key


I came to this question searching for the reason of the same MDN warning as OP. After searching some more, the issue with keyCode becomes more clear:

The problem with using keyCode is that non-English keyboards can produce different outputs and even keyboards with different layouts can produce inconsistent results. Plus, there was the case of

If you read the W3C spec: https://www.w3.org/TR/uievents/#interface-keyboardevent

In practice, keyCode and charCode are inconsistent across platforms and even the same implementation on different operating systems or using different localizations.

It goes into some depth describing what was wrong with keyCode: https://www.w3.org/TR/uievents/#legacy-key-attributes

These features were never formally specified and the current browser implementations vary in significant ways. The large amount of legacy content, including script libraries, that relies upon detecting the user agent and acting accordingly means that any attempt to formalize these legacy attributes and events would risk breaking as much content as it would fix or enable. Additionally, these attributes are not suitable for international usage, nor do they address accessibility concerns.

So, after establishing the reason why the legacy keyCode was replaced, let's look at what you need to do today:

  1. All modern browsers support the new properties (key and code).
  2. IE and Edge support an older version of the spec, which has different names for some keys. You can use a shim for it: https://github.com/shvaikalesh/shim-keyboard-event-key (or roll your own - it's rather small anyways)
  3. Edge has fixed this bug in the latest release (probably will be released in Apr 2018) - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
  4. Refer to the list of event keys you can use: https://www.w3.org/TR/uievents-key/
kumarharsh
  • 18,961
  • 8
  • 72
  • 100
  • [**According to the MDN**](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code), neither Internet Explorer nor Edge support `KeyboardEvent.code`. Also, the values for `key` and `code` are browser dependent. Both issues making `key` and `code` not practical to use in real life applications. – John Slegers Apr 18 '18 at 19:33
  • @JohnSlegers please see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key – kumarharsh Apr 19 '18 at 02:06
  • 1
    If I want to test the arrow keys, page up/down, home & end, should I use `key` or `code`? It's generally a physical key, but can depend on Num Lock and layout too... What's the best practice? – Jake Nov 04 '18 at 22:54
  • 3
    It being a `string` also makes it a lot more readable, so it is advisable to use it for all new code. For maintaining legacy, it will depend on how much you depend on it being a `number`. Just be aware that when you hit a printable key, `event.key` "a" and "A" are different while `event.code` will be "keyA" for both. For non printable, you can have `event.code` being "ShiftLeft" or "ShiftRight" while `event.key` will be "Shift" for both. – Guilherme Taffarel Bergamin Jan 25 '21 at 17:41
33

In addition that all of keyCode, which, charCode and keyIdentifier are deprecated :
charCode and keyIdentifier are non-standard features.
keyIdentifier is removed as of Chrome 54 and Opera 41.0
keyCode returns 0, on keypress event with normal characters on FF.

The key property :

 readonly attribute DOMString key

Holds a key attribute value corresponding to the key pressed

As of the time of this writing, the key property is supported by all major browsers as of : Firefox 52, Chrome 55, Safari 10.1, Opera 46. Except Internet Explorer 11 which has : non-standard key identifiers and incorrect behavior with AltGraph. More info
If that is important and/or backward compatibility is, then you can use feature detection as in the following code :

Notice that the keyvalue is different from keyCode or which properties in that : it contains the name of the key not its code. If your program needs characters' codes then you can make use of charCodeAt(). For single printable characters you can use charCodeAt(), if you're dealing with keys whose values contains multiple characters like ArrowUp chances are : you are testing for special keys and take actions accordingly. So try implementing a table of keys' values and their corresponding codes charCodeArr["ArrowUp"]=38, charCodeArr["Enter"]=13,charCodeArr[Escape]=27... and so on, please take a look at Key Values and their corresponding codes

if(e.key!=undefined){
        var characterCode = charCodeArr[e.key] || e.key.charCodeAt(0);
    }else{
        /* As @Leonid suggeted   */
        var characterCode = e.which || e.charCode || e.keyCode || 0;
    }
        /* ... code making use of characterCode variable  */  

May be you want to consider forward compatibility i.e use the legacy properties while they're available, and only when dropped switch to the new ones :

if(e.which || e.charCode || e.keyCode ){
        var characterCode = e.which || e.charCode || e.keyCode;
    }else if (e.key!=undefined){
        var characterCode = charCodeArr[e.key] || e.key.charCodeAt(0);
    }else{
        var characterCode = 0;
    }

See also : the KeyboardEvent.code property docs and some more details in this answer.

user10089632
  • 5,216
  • 1
  • 26
  • 34
  • 1
    You solution doesn't work in my browser (Windows 10, Chrome 60, Belgian keyboard). First of all, the `charCodeArr` function does not exist. Also, `charCodeAt` doesn't work for all values of `e.key`. For example, for the `Enter` / `Return` key, the value of `e.key` property is `"Enter"`, and executing `charCodeArr` for that string returns the value `69` (which is the ASCII code for the character `E`). – John Slegers Aug 24 '17 at 11:06
  • @JohnSlegers, yes that was a typo, I meant a user built array. Please, see my updated answer for more details. – user10089632 Aug 24 '17 at 12:37
18

MDN has already provided a solution:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

window.addEventListener("keydown", function (event) {
  if (event.defaultPrevented) {
    return; // Should do nothing if the default action has been cancelled
  }

  var handled = false;
  if (event.key !== undefined) {
    // Handle the event with KeyboardEvent.key and set handled true.
  } else if (event.keyIdentifier !== undefined) {
    // Handle the event with KeyboardEvent.keyIdentifier and set handled true.
  } else if (event.keyCode !== undefined) {
    // Handle the event with KeyboardEvent.keyCode and set handled true.
  }

  if (handled) {
    // Suppress "double action" if event handled
    event.preventDefault();
  }
}, true);
Vicky Gonsalves
  • 11,593
  • 2
  • 37
  • 58
  • 5
    Unfortunately, `key` is a browser-specific string value like `"Enter"` or `"ArrowUp"` and there's no standardized way to convert it to the corresponding code. so you're going to need even more boilerplate code to convert between key & code. – John Slegers Aug 24 '17 at 11:27
7

e.charCode has been deprecated:

<input
  onChange={(e) => setToken(e.target.value)}
  type="text"
  value={token}
  onKeyPress={(e) => {
    if (e.charCode === 13) {
      verifyLoginF()
    }
  }}
/>

enter image description here

you should use now:e.key === 'Enter'

enter image description here

Alan
  • 9,167
  • 4
  • 52
  • 70
2

Here was proposed to use key value instead of keyCode and if it fails then use keyCode. Though this is not enough, because values in this attributes are not compatible. Thing is new key contains the string for control keys, like: ArrowUp, but keyCode will contain just code which with trivial

String.fromCharCode(event.keyCode)

will result in a non-printable char. Here the solution for printable chars:

element.keydown((event) => {
    var symbolPressed;
    //cross browser
    if (event.key !== undefined) {
        symbolPressed = event.key; //Here control characters represented as String like: ArrowUp
        if (symbolPressed.length > 1) return; //filter out control characters
    } else if (event.keyCode !== undefined) {
        symbolPressed = String.fromCharCode(event.keyCode); //Here control chars represented as one char string
    }
    //Update this regex if you need other characters
    if (!symbolPressed.match(/[A-z0-9\s]/)) return;
    console.log(symbolPressed);
});

And in case of you need non-printable control characters, you have to update conditions and regex accordingly.

P_M
  • 2,723
  • 4
  • 29
  • 62
0

Using onkeypress and onkeydown to event.which, it is switch [CHARACTER code] or [KEYcode]

 function myKey(event){
 
  var keycode = event.keyCode;  //key code variant 1, not recomendate
  var keywhic = event.which;    //key code variant 2, nice worked 
  var unicode = event.key;      //string name code, nice worked  
  var chacode = event.charCode; //works onkeypress="myKey(event)"
  var metakey = event.metaKey;  //true false, winKey or macComand
  
  document.getElementById("demo").innerHTML = keycode+" "+keywhic+" "+unicode+" "+chacode+" "+metakey;
}
<!DOCTYPE html>
<html>
<body onkeydown="myKey(event)"> <!--onkeypress="myKey(event)"-->

<h1 id="demo">Keyboard Buttons click me and test the keyboard</h1>
<script>
 //function myKey(event){
 //paste code
 //}
</script>
</body>
</html>
Cody toys
  • 11
  • 1
-5

You can use

parseInt(event.key, radix: 10)
theWellHopeErr
  • 1,856
  • 7
  • 22
  • 5
    Please don't post only code as an answer, but also provide an explanation of what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes – Ran Marciano Dec 08 '20 at 06:34