During the past 15 months, I have been thinking a lot about keyboard shortcuts and about how different applications handle them. I shouldn’t complain; I knew what I was getting into when I started to build KeyCombiner, an app for learning and looking up shortcuts and text snippets. Still, I didn’t quite know how much of a mess keyboard shortcut handling on the web is.
Do you use an international keyboard layout? Then you already know what I am talking about. You probably have had some issues typing keyboard shortcuts such as alt+/, or cmd+[. This post will help you to understand why this annoyance exists. However, the people who should most urgently read this post are web developers. Are you a web developer? Great! I will explain how you are currently letting down non-US users and how you can get us out of this mess.
I will focus on web applications. The behavior on desktop apps is often different. However, with the rise of Electron apps, web technologies are ever-present on the desktop as well. So, the arguments in this article probably apply to half of your installed apps as well.
Examples of Broken Apps
The problem I am talking about is so incredibly omnipresent that most international users are just used to the fact that they cannot type a good portion of a given web application’s keyboard shortcuts on their keyboards. However, web applications are becoming increasingly complex, and they are rapidly replacing desktop applications, making this problem bigger by the day.
This is most annoying when the most important keyboard shortcuts are inaccessible. A very common shortcut is / for accessing search functionality. Unfortunately, there is no /-key on most international layouts. Adding modifiers to produce this key with your layout rarely helps. For example, on my German layout, / is produced via Shift+7. Most web applications will ignore this. Similarly painful is when Electron apps use [ and ] for navigating backwards and forwards.
If you use a US layout, you might be surprised to hear about these problems. But rest assured, they are not new and I am not the only one who is affected. We are at a point where it is easy to find users complaining about this for almost any popular web application.
An interesting example are Google’s apps. For some reason, Google manages to handle international layouts correctly in Gmail, but fails to do so in any of its other applications. The web is full of complaints, e.g. for Google Sheets, Google Drive, and Google Docs.
Another, almost funny examply is Figma, the popular web-based vector-graphics editor. So many people complained that there is now a dedicated site with workarounds for different layouts.
This complaint in the Asana forums is funny too. They made some specific adjustments for some layouts, only to give up in the end and say that they will still not support more exotic layouts.
Finding all these applications with broken shortcut handling was very easy. I used KeyCombiner’s shortcut search to find all applications that use the US /-key in their shortcuts. Then I googled and found complaints for most of these apps. In the case of Notion and Google Drive/Docs/Sheets, I was already aware simply because I use these applications myself.
I want to be clear, broken keyboard shortcuts are not a law of nature. It is possible to implement web application shortcuts so that they can be typed with any layout. It shouldn’t be an excuse that even some of the most popular apps do not get it right.
Why is this happening?
What baffles me is that the problem exists in apps used by millions of people every day, developed by gigantic corporations who pride themselves with having the best engineers in the world. Why is this baffling? Because the underlying technical issues are rather trivial!
let key = event.keyCode || event.which || event.charCode;
charCode to find out which key was pressed. Why is this a problem? For starters, all three properties are deprecated. That isn’t even the main problem though. These event properties are simply not suited for finding out which character was pressed, at least when used with
keyup. Still a vast majority of web applications use the
keydown evente with these properties.
It is very clearly documented that this should not be done and that it is not compatible across layouts, operating systems, and even browsers. To cite the MDN web docs:
Web developers shouldn’t use the keyCode attribute for printable characters when handling keydown and keyup events. As described above, the keyCode attribute is not useful for printable characters, especially those input with the Shift or Alt key pressed. When implementing a shortcut key handler, the keypress event is usually better.
Using Chrome on Linux with a german keyboard, my # key will produce the required
keyCode for triggering / shortcuts. However, this does not work on Firefox, and neither does it work on Chrome on macOS. With many browser and OS combinations, there is no way to trigger this shortcut on a german layout. The same goes for many other international keyboard layouts that do not have a dedicated /-key.
If you want to see which button presses produce which event properties, you can use this neat little web tool:
Hint for developers: Switch your computer’s keyboard layout to something other than US to debug your application’s shortcut handling on different layouts.
Using this event viewer, you will see that the
keypress event usually produces the correct code on any layout. Unfortunately, this event is deprecated as a whole and comes with its own problems. Still, the Mousetrap library can use the
keypress event with fairly good results on international layouts.
As you can see, the situation is messy. However, developers are usually pretty good at dealing with complex problems. In the next section, I will point out some straightforward ways to do better than Google and other tech giants.
How you can do better
The good news is that this problem is easy to fix. Depending on your resources and the technical and semantical requirements of your application, there are a few things that you could do:
If your web application does not have a huge amount of shortcuts, or if you don’t have the resources to spend a meaningful amount of engineering work on this problem, here are some trivial ways to work around the described issues.
Do not use special characters for your keyboard shortcuts.
That’s all you would need to do to make 99% of your international users happy. If you want to go one step further, you can try to stay on the home row or choose otherwise easy-to-type characters. In case you have an existing application with shortcuts that cannot be changed because your American users already learned them, consider the suggestion below.
If you really do need to use special characters, provide alternatives that can be typed on all keyboard layouts. Both HotKeys.js and Mousetrap support multiple triggers when creating your bindings. For example if you have / as you shortcut for focusing the search field because your US users are accustomed to this behavior, just add alt+s as an alternative for international users. Some US users might welcome this change as well, because alt+s can be typed with just the left hand while / reqiures people to take their hand of the mouse.
Actually make the shortcuts work with any keyboard layout.
This means when the key combination is alt+/, the shortcut should be triggered when a german layout user presses alt+shift+7. This is surprisingly easy with some of the popular shortcut processing libraries. With Mousetrap, all you need to do is listen to the
keypress events instead of
keydown. In the next section of this post, I will mention some applications that work this way.
Unfortunately, there is a minor downside to this approach. It can make some shortcuts tedious to type on some layouts, e.g. requiring two or three modifiers. It also has some potential for shortcut conflicts. Ctrl+/ is suddenly the same as ctrl+shift+7. You should be aware of that and not assign these things to two different bindings. The easiest way to avoid such conflicts is by staying away from the Shift modifier when defining your bindings.
If you want to go all the way, you could write your own shortcut processing code, and possibly make it into an open-source library. The current alternatives do not care too much about supporting different layouts.
There are a lot of things one could do to solve all the issues described in this article. For example, you could use the
key attribute, or even play around with the experimental
keyboard.getLayoutMap API. KeyCombiner uses this API to display its on-screen virtual keyboards with the user’s layout.
Sometimes, I think about making such a library myself. KeyCombiner already uses a fork of Mousetrap that has been customized quite a bit. However, I already have a demanding full-time job and a large side-project, so I would be happy if you beat me to it.
Allow users to change the default key bindings.
This way, users of international keyboard layouts, can change invalid bindings to something that works for them. As a bonus, you would make any shortcut enthusiast happy, and your marketing people could point out how all your sorry-ass competitors do not allow custom keyboard shortcuts.
Interestingly, I am not aware of a single web application that lets you customize keyboard shortcuts, even though it wouldn’t be that difficult to implement, especially with modern SPAs that would have to pull the custom bindings from the database only once. You could store them in your database, pull them out when a user logs in, and pass them to your shortcut processing library.
Wall of Fame
Fortunately, some applications already do it right. Three apps that I am using where my german layout works flawlessly are Gmail, Linear, and Discourse.
It’s hard to believe that Gmail is created by the same company as Google Drive, Google Chat, and many other apps that do not handle shortcuts correctly on international layouts. The Gmail web interface works great on all layouts that I tested. On my german layout, I can even use AltGr+8 to archive a conversation ([). Similarly, search can be triggered via shift+7 (/). Note that this is the exact same shortcut that does not work in all the other Google apps. So, if you work at Google, maybe ask your colleagues on the Gmail team for a little help.
Discourse is a great example because it is an open-source application, meaning that you can go to their GitHub repository and see how they are doing it. The answer is very simple: They use the Mousetrap library with
keypress. As explained above,
charCode will contain the right code even on international layouts when used with
Linear is a relatively new and increasingly popular issue tracking software. It takes pride in having a keyboard first design, and being optimized for efficiency with extensive keyboard shortcuts. Their recent success story and my personal experience suggest that they deliver on this promise. Of course, many other web apps have a lot of keyboard shortcuts, too. However, with Linear, they actually work.
Do you know other applications that work with all keyboard layouts? Please let me know in the comments below, and I will add them here.
Next time you use an app that dangles its keyboard shortcut definitions in front of you, just so you can find out that they don’t work with your layout, please remember this post. You will know that there are ways to fix this.
If you are in the mood, you can write a nice message to the developers, explaining how they are probably misusing the
keydown event and its
keyCode property. We shouldn’t have to live like this.