I would expect most people’s impression of sticky keys is “that annoying feature which activates when you accidentally press Shift for a few times”. I had that moment about 15 years ago on a Windows XP, but recently discovered that it is truly a gem hidden in plain sight that’s not only an ergonomic paradise, but also has the power to fundamentally change the way I interact with my computer.

A short introduction on how sticky keys work: Sticky keys are like the Shift key on smart phone keyboards, pressing it once will capitalize the next character, and pressing it twice enters CapsLock mode until you press it again which will reset it to the default state. In macOS, upon enabling this in Accessibility > Keyboard, this will make all your modifier keys (Command , Shift , Ctrl ^, Options , Fn) act in this way, but one thing unlike smartphone keyboard is that you can still use the modifier keys in the old way, and they won’t “stick” as long as you pressed another key before releasing the modifier. There are visual aids telling you which modifiers are currently “stuck” and which are “locked”.

The visual aids in macOS: This indicates that the next key stroke will be modified by Command, Shift, and Ctrl. After which Command and Shift will be reset and Ctrl will remain active until you press it again.

This post discusses the many reasons of why sticky keys are awesome, and talks a little about my personal philosophy on how should keyboards be configured at the end.

Table of Contents

  1. Smooth Learning Process
  2. Comfort: No More Chording / System-Wide Leader Keys!
  3. No Sacrifice in Speed (and Potentially Faster!)
  4. Put Modifier Keys Anywhere
  5. Free CapsLock!
  6. Layering at the Right Layer of Abstraction
  7. The Bad and the Ugly
  8. Conclusion
  9. Update 2021-11-03

Smooth Learning Process

Unlike more radical things such as switching to Dvorak, after enabling sticky keys, you can still use your keyboard the old way without any issue, and it could come in handy once in a while (e.g. when taking a screenshot with ⌘+Shift+Control+4).

I am saying this because I switched to Dvorak about 6 years ago, even though it was one of the best decisions I have ever made, the transitional phase of being stuck between the muscle memory of Qwerty and Dvorak was a huge pain.

Comfort: No More Chording / System-Wide Leader Keys!

Chording is bad for your fingers, and the our modifier-addicted friends know it very well. Sticky keys solve this problem by enabling you to gracefully press each modifier keys in succession and then the modified key.

Vim users that are obsessed with tinkering with their configuration (like me) often make heavy use of “Leader Key”. TLDR: Leader key is the first key in many key strokes sequences that get mapped into different editor actions. The gist is that you press them in succession (like Space-u-m) rather than together (like Ctrl+Shift+g, a.k.a. chording). Leader key sequences are so comfortable that even our mortal enemies became jealous and invented Spacemacs which is based on the stolen idea of using Space as the leader key for editor actions and save themselves from Emacs pinky commonly caused by their inferior shortcut design (/s, of course). Here’s a peek at the leader shortcut section of my .vimrc (using Space as leader):

nnoremap <Leader>n gt
nnoremap <Leader>p gT
nnoremap <Leader>q :q<CR>
nnoremap <Leader>s :w<CR>
nnoremap <Leader>ug :Goyo<CR>
nnoremap <Leader>un :noh<CR>
nnoremap <Leader>ul :Limelight!!<CR>
nnoremap <Leader>ut :TagbarToggle<CR>
nnoremap <Leader>up :set nopaste<CR>
nnoremap <Leader>x :x<CR>

With sticky keys enabled, it’s basically system-wide leader keys. Taking a screenshot with ⌘+Shift+Ctrl+4 is a pain? Just press them one-by-one (with any modifier order)!

No Sacrifice in Speed (and Potentially Faster!)

Disclaimer: I value the comfort of typing much more than speed, as typing speed is rarely the bottleneck of my productivity. This section is just to demonstrate that comfort of sticky keys does not come at the cost of speed.

As sticky keys completely removes the need for holding a key down, less effort/strain is needed. But what about the speed? Essentially, sticky keys removed the requirement on when to release the modifier keys, and actions happen when a key is depressed, so at the very least using sticky keys should not slow you down.

But I would like to go one step further and argue that using sticky keys actually make you faster. Assuming we have 3 movements:

  • $m_1$: Pressing a key and releasing it immediately.
  • $m_2$: Press down a key and hold it.
  • $m_3$: Release a key that is being held down.

Let $\mathrm{t}(m)$ denote the length of time between beginning $m$ and being ready for next action.

First of all, $\mathrm{t}(m_1) \ne \mathrm{t}(m_2) + \mathrm{t}(m_3)$. Try it on your keyboard and feel how it’s different when you simply stroke a key vs. press and hold then release. If you are using a mechanical keyboard and with the right switch and enough experience, you can consistently press the key with just enough force to actuate it without ever reaching the bottom of the travel (“bottoming out”). I would estimate their relationship to be something like: $\mathrm{t}(m_1) \approx \mathrm{t}(m_2) \approx \mathrm{t}(m_3)$.

Now imagine typing a ctrl+h b where ctrl+h is the {readline, Emacs, Vim, Bash, macOS} shortcut for deleting the last character (and perhaps one of my most used key bindings of all time (even though I hate to admit it)).

Without sticky keys:

  • $m_1$: a
  • $m_2$: ctrl down
  • $m_1$: h
  • $m_3$: ctrl up
  • $m_1$: b

With sticky keys:

  • $m_1$: a
  • $m_1$: ctrl
  • $m_1$: h
  • $m_1$: b

If our assumption of $\mathrm{t}(m_1) \approx \mathrm{t}(m_2) \approx \mathrm{t}(m_3)$ is true then this is already a 20% reduction in time usage in our tiny example.

However the same strategy would not be work for cases where you need to type consecutive keys with the same modifier, such as my favorite Vim insert mode Ctrl chain such as C+pemdc (go up one line, go to end of line, insert newline, dedent current line, exit insert mode). In those cases, we have two choices:

  1. Lock the modifier and reset lock:

    \[(2 + 5 + 1) \times \mathrm{t}(m_1) \approx 8 \mathrm{t}(m_1)\]
  2. Just use the traditional way which sticky key allows:

    \[5 \times \mathrm{t}(m_1) + \mathrm{t}(m_2) + \mathrm{t}(m_3) \approx 7 \mathrm{t}(m_1)\]

The traditional way wins by 1 unit, but I suspect that if we take into account the reduction in speed caused by the restriction of movement when one finger is depressing the modifier key, sticky keys could still win.

Then again as I mentioned at the beginning of this section, speed is not the point. It’s about feeling more comfortable typing without sacrifice in speed.

Put Modifier Keys Anywhere

Modifier are traditionally place on both sides and pressed by pinkies on the opposite side of the modified key (e.g. Shift and Ctrl). As pinky is relatively weak when compared with other fingers, some ergonomic keyboards has “thumb clusters” for modifiers (e.g. Kinesis Advantage, Ergodox, Keyboardio), this has several advantages:

  • No need for having one modifier on each side because thumb is not used for letter/number keys
  • Reduce pinky strain and avoid “Emacs pinky”

However, in practice I have found that thumb is equally prone to strain injuries after long typing sessions, and this topic often comes up in discussions about Ergodox’s suboptimal thumb cluster placement, Xah Lee has an excellent summary on Ergodox’s thumb cluster issues here. I suspect that this may be due to the fact that the natural “press” direction of the thumb is very different from the other fingers and most keyboards available does not optimize for this (except Manuform and its derivatives such as Dactyl Manuform).

Sticky keys makes it possible to assign modifier keys to index and middle fingers, without need for assigning another key on the opposite hand. The probability of the modifier and the modified being on the same finger is low ($\approx \frac{1}{8}$), and even if that happens, they can be pressed in succession.

Free CapsLock!

By just double tapping Shift! You will appreciate it next time when you are typing those #ifndef SUPER_LONG_HEADER_PATH_THAT_BREAKS_THE_BOUNDARY_OF_REALITY_WHICH_IS_EIGHTY_CHARACTERS_ and ANNOYING_PREPROCESSOR_MACROS(). Really, even typing TODO requires you to switch hands a few times if you always use the Shift key on the opposite side to avoid cramping.

Some background for those who still has CapsLock on their keyboard (from https://www.emacswiki.org/emacs/MovingTheCtrlKey):

For some, swapping Control and CapsLock is very important; the virtually useless CapsLock is far easier to press than Control, crucial to Emacs yet really awkwardly located.

When Emacs was first written, most keyboards had Ctrl to the left of A, either immediately to the left or with CapsLock in between. Thus, it was a convenient and logical choice of key for creating Emacs commands. When personal computers went mainstream in the 80’s, Ctrl was moved out of the way, presumably because the target users (office workers) wouldn’t need Ctrl as often as CapsLock.

Layering at the Right Layer of Abstraction

Warning: This section is more about my personal philosophy and may be controversial, read with a grain of salt.

I always disliked those 40% keyboards that hides tons of keys behind layers, and it’s not due to the overhead of switching layers (as I mentioned earlier speed is not what I’m looking for).

Let’s start with a simple example: Arrow keys. Disclaimer: Being a Vim user with system-wide ctrl-p/n/b/f arrow key shortcuts, I rarely need arrow keys. But when I do, it is a part of some shortcuts such as Ctrl+Left/Right for switching workspace. Now if my arrow keys are behind some other layers, they will be from difficult to impossible for being used in a shortcut sequence. Then 40% keyboard enthusiasts will start talking about QMK and telling me that I can just remap something like Fn+H to Ctrl+Left. Cool, but there are so many shortcuts for macOS and each application, which means that if I assign this very convenient home-row key to Chrome, I won’t be able to use it for any other application. Convenient keys (like the ones on home row) are a scarce resource. Mapping things on keyboard won’t let me have the most convenient keys function differently in different applications, because keyboard is the wrong place for creating system/application-specific shortcuts!

Here’s an attempt to express the same sentiment by misinterpreting the SOLID principles:

  • Single-Responsibility: A keyboard should only be responsible for producing key signals ergonomically, but not in charge of the behavior of specific applications.
  • Open-Closed: You should be able to extend system/application key binding behaviors without modding your keyboard.
  • Liskov Substitution: You should be able to switch to any other keyboard for your computer without losing functionalities.
  • Interface Segregation: The convenient key locations for a specific application should not be taken up by the bindings optimized for another application.
  • Dependency Inversion: Keyboard configuration should not depend on what specific applications you have on your computer, neither should how the behavior of your application depend which keyboard you are using. They should both depend on the common interface (key codes and press/release signals).

So what’s the right way to do this then? I believe the best place for creating those bindings is from within the operating system with per-application shortcuts. For example, in Chrome, switching tabs is one of my most commonly used operations, and at the same time I am not using the most convenient keys ⌘+h and ⌘+n at all, therefore I have created mappings for ⌘+h -> Ctrl+Shift+Tab and ⌘+n -> Ctrl+Tab, along with several things like PageUp/PageDown. Now I have effectively created a “Chrome layer”, which activates when I press ⌘ once in Chrome, and locks when I press ⌘ twice. Also with the system-wide mapping from Ctrl-p/n/b/f to arrow keys, double tapping Ctrl essentially brings me to the “Fn” layer with arrow keys and a lot more.

QMK has something similar called “Tap Dance” that allows assigning different actions to consecutive taps, but sticky keys still win in three ways:

  1. I can get this on any keyboard, even on the crappy built-in butterfly keyboard which I have to use once in a while for meetings etc. (Good luck flashing QMK on your laptop keyboard)
  2. I get a visual indication on screen about the current “layer” than I’m in.
  3. I can reuse the convenient keys for different purposes in other applications (e.g. use ⌘+h for cancelling a to-do item in Things).

The Bad and the Ugly

The sticky keys on macOS (as of 10.15.4) seems to be implemented by releasing the modifier really quick after modifying one key, so there’s the possibility of accidentally modifying more than one keys for a single stick if you are typing fast enough. This happens sometimes when I type “The” which could become “THe”. But I have been consciously limiting my typing speed for higher accuracy these days so it doesn’t bother me too much, but I do see the potential of this being a great annoyance.

Conclusion

Sticky keys are awesome and you should use them!

Update 2021-11-03

I have recently ditched macOS’s native sticky keys implementation in favor of Karabiner’s implementation, because:

  1. It doesn’t have the “THe” issue of native sticky keys, I can type as fast as I want
  2. Possibly due to the same underlying implementation difference, subjectively, it is much faster and far more responsive than the native sticky keys
  3. It doesn’t have latchlock (press twice to lock, and press a third time to unlock), which I initially overrated. It is rarely useful, and when you mistype a modifier, you’ll need to double-press to cancel it.