I come across a lot of posts which lack proper hotkey formatting: any key

And I change it to: AnyKey

It would save me 11 keystrokes per <kbd></kbd> if there was a button in the post editor toolbar.

Is there a way to add it? Or is it solely managed by SE?

UX has a unique wireframe-editor button, so there seem to be differences...

  • 10
    $\begingroup$ Any reason to not have this for users without moderator rights too? $\endgroup$
    – gandalf3
    Commented May 4, 2014 at 2:11
  • $\begingroup$ I worry it could be abused by new users to highlight anything but shortcuts. $\endgroup$
    – CodeManX
    Commented May 4, 2014 at 13:25
  • 1
    $\begingroup$ We already have that issue to some extent with the existing formatting options (mainly with backtics). We'll just have to edit these when needed. Users that stay around will eventually catch on (if not, we can just leave a comment pointing the the style guide meta). $\endgroup$
    – gandalf3
    Commented Jul 16, 2014 at 9:00

4 Answers 4


I have made a variant of the script posted by CoDEmanX with:

  • Multi-char support

  • A keyboard shortcut (CtrlY, if you think of a better available key, please comment)

  • Optional key/mousebutton icons

  • Support for reviewing/improving edits, answering own questions, etc.

  • Undo support

  • An icon

  • Automatic extra space removal

Example of usage:

enter image description here

Tested on Firefox 59.0.2 and Chromium 65.0.3325.181.
Recommended to install with Tampermonkey for chrome users.


Please forgive my less-than-polished js skills..

  • $\begingroup$ Nice additions gandalf! The problem with Chrome might be the sandboxing, since we inject the user script from another source (file:/// or localhost respectively)... The shortcut is not going to work for edits, 'cause it uses an ID: $("#wmd-input").keydown(...). You might want to bind it to the class .wmd-input instead. There's a } too much at the end it seems. $\endgroup$
    – CodeManX
    Commented May 5, 2014 at 3:54
  • $\begingroup$ Hm ok, that } is needed, the Firefox code highlighter just can't find the matching one of main() {? Very strange. The button works like a charm, but the shortcut doesn't. Ctrl+E places the cursor in the quick search field in Firefox, Y does nothing and Z is for undo (Z and Y are swapped on German keyboards, so I checked that too...). There's a feature missing from my script: the cursor placing after button use. With no text selected, it should insert a kbd-tag and place cursor inbetween, otherwise add tags and place cursor behind the last. Also focus() the textarea in both cases. $\endgroup$
    – CodeManX
    Commented May 5, 2014 at 4:07
  • $\begingroup$ Ok, I fixed some problems and optimized the embedded icon, works for me in Firefox. Hotkey is a bit problematic it seems, doesn't work in some cases. Back-ported my cursor placement. userscripts.org/scripts/review/486617 $\endgroup$
    – CodeManX
    Commented May 5, 2014 at 5:13
  • $\begingroup$ Mystery solved: the deprecated .live() worked for the hotkey, but .on() didn't - 'cause it needs to be used on document and the elements we are interested in are given as second parameter as filter! Works like charm! $\endgroup$
    – CodeManX
    Commented May 5, 2014 at 5:36
  • $\begingroup$ Brilliant :) I didn't do anything, but the hotkey didn't give me any trouble.. On my FF Ctrl E does nothing, however chrome puts it in the url bar, so I guess that's a no go either way. It would be nice to have a key a bit closer to left Ctrl, but it doesn't look like there is one free. Is it worth breaking the theme of using Ctrl to use Alt+nearby-sensible-letter or something instead? $\endgroup$
    – gandalf3
    Commented May 5, 2014 at 8:27
  • $\begingroup$ I added extra space removal, so now extra spaces are removed automatically. I also scaled down the icon to 20px so it fits better, but as a result un-optimized it again :/ (idk how to optimize it). I tried to get the button li to go after the image button (it seems like the right category to me) by replacing appendTo with insertAfter("#wmd-image-button"), but it still goes at the end?? $\endgroup$
    – gandalf3
    Commented May 5, 2014 at 8:30
  • $\begingroup$ Wow, this is really nice. Great job guys. Can we agree on one final version. @gandalf3 Would recommend uploading to userscripts.org so it can be 1 click installation. $\endgroup$
    – iKlsR
    Commented May 5, 2014 at 8:34
  • $\begingroup$ @iKlsR Okay. Still not quite done yet, still some kinks imo (plus it's currently not working on chrome, looking at that now). Working again, jquery was used before it was loaded.. $\endgroup$
    – gandalf3
    Commented May 5, 2014 at 8:36
  • $\begingroup$ Really didn't see the need for a dependency tho. $\endgroup$
    – iKlsR
    Commented May 5, 2014 at 9:08
  • $\begingroup$ For me, Ctrl+Y is fine, 'cause it's the closest key to Left Ctrl on my German keyboard ;) Ctrl+E is used by both browsers, so better not overwrite default behavior. You can optimize PNGs using tinypng.com, which uses pngquant.org. insertAfter doesn't work, 'cause every button has an offset (left: 25px * n, where n is the index). To insert another button, you would have to get the previous offset and add 25px to your and all subsequent buttons. @iKlsR: It did not work on Chrome apparantly, might be caused by its sandboxing / same-origin-policy. It does in Firefox however. $\endgroup$
    – CodeManX
    Commented May 5, 2014 at 14:01
  • 1
    $\begingroup$ I made an adaptation of it for Blender Community, just the keyboard shortcut part. $\endgroup$
    – Lauloque Mod
    Commented Jan 2 at 23:39

Thanks iKlsR, I created a Greasemonkey script based on your code, which inserts a new button automatically:

// ==UserScript==
// @name        Add <kbd> Button to StackExchange Toolbar
// @namespace   http://blender.org
// @include     *.stackexchange.com/*
// @version     1
// @grant       none
// ==/UserScript==

var toolbar;
function toolbar_wait() {
    toolbar = document.getElementById('wmd-button-row');
    if (toolbar == null) {
        window.setTimeout(toolbar_wait, 500);
    } else {

function insert_kbd()
    var txta = document.getElementById('wmd-input');
    if (txta.selectionStart == null) return;
    var chars = txta.value.split("");
    chars.splice(txta.selectionStart, 0, '<kbd>');
    chars.splice(txta.selectionEnd + 1, 0, '</kbd>');
    txta.value = chars.join("");

function toolbar_add() {

    var style = document.createElement('style');
    style.setAttribute('type', 'text/css');
    style.innerHTML = '#wmd-kbd-button:hover {background-color: #deedff;}';

    var li = document.createElement('li');
    li.onclick = insert_kbd;
    li.setAttribute('style', 'font-size: 9pt; left: 400px;');
    li.setAttribute('title', 'Keyboard Shortcut <kbd>')
    li.setAttribute('id', 'wmd-kbd-button')
    li.className = 'wmd-button';

    var span = document.createElement('span');
    span.innerHTML = 'kbd';
    span.setAttribute('style', 'background-image:none;');

function toolbar_update() {

    var element = document.getElementById('wmd-input');

    var keyboardEvent = document.createEvent("KeyboardEvent");
    var initMethod = typeof keyboardEvent.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent";

                   "keydown", // event type : keydown, keyup, keypress
                    true, // bubbles
                    true, // cancelable
                    window, // viewArg: should be window
                    false, // ctrlKeyArg
                    false, // altKeyArg
                    false, // shiftKeyArg
                    false, // metaKeyArg
                    17, // keyCodeArg : unsigned long the virtual key code, else 0
                    0 // charCodeArgs : unsigned long the Unicode character associated with the depressed key, else 0


Install: https://userscripts-mirror.org/scripts/show/486617

I added a hack to simulate a keydown event (ctrl) to make the live markdown preview update. Tested and working in Firefox 28.

  • $\begingroup$ Installed via Tampermonkey and working on latest version of chrome as well. Really nice. Thanks. I couldn't figure how to get the live update so I just opted to have it trigger with other user input after. ;) $\endgroup$
    – iKlsR
    Commented May 4, 2014 at 15:40
  • $\begingroup$ I initially had it binded to wmd-input too but changed it as I thought since I was using a bookmarklet it could be useful elsewhere as well. $\endgroup$
    – iKlsR
    Commented May 4, 2014 at 15:45
  • $\begingroup$ <kbd> isn't supported in comment anyway, I use backticks instead. Thanks for testing! Now, should I accept my own answer or yours? $\endgroup$
    – CodeManX
    Commented May 4, 2014 at 16:31
  • $\begingroup$ Tested on Chrome OS X & it works GREAT if I'm creating an answer, but the kbd button is not there if I try to edit an existing answer. $\endgroup$ Commented May 4, 2014 at 16:57
  • $\begingroup$ @CoDEmanX Yours will do. I mean't elsewhere, not comments, we all use backticks ;). I need some sleep. $\endgroup$
    – iKlsR
    Commented May 4, 2014 at 18:15
  • $\begingroup$ Alright! I updated the script to use jQuery and made it work that it also injects the button if you edit posts. Hope it still works for everyone. I couldn't find a jQuery-way of updating the markdown preview, so left that untouched for now and created a question on SO: stackoverflow.com/questions/23460904/… $\endgroup$
    – CodeManX
    Commented May 4, 2014 at 20:02

Such a feature is not available in the formatting toolbar, you have to do it manually. I've often wanted the same feature as it is encouraged that posts be formatted correctly, especially input.

My javascript is really, really rusty but I managed to throw something together that should save a bit of time (a few seconds at least ;) when doing this.


  1. Drag this line of code to your bookmarks bar, raw. (only tested on chrome and firefox).

    javascript:(function(){var txta = document.activeElement; if (txta.selectionStart == undefined) return; var chars = txta.value.split(""); chars.splice(txta.selectionStart, 0, '<kbd>'); chars.splice(txta.selectionEnd + 1, 0, '</kbd>'); txta.value = chars.join("");})()
  2. You can then rename the newly created bookmark to something useful.


Select the text to be wrapped in the textarea and click the bookmark.

  • $\begingroup$ Someone who has a few minutes to spare could convert this into a userscript and have it fit nicely in the formatting toolbar methinks. $\endgroup$
    – iKlsR
    Commented May 4, 2014 at 7:12
  • $\begingroup$ Never made user scripts before, but I'll give it a go :) $\endgroup$
    – gandalf3
    Commented May 4, 2014 at 7:17
  • $\begingroup$ Super awesome! One question: on my OS X with Chrome, for some reason the formatting does not display in the formatting preview until I press some other key in the editing window. I'm not complaining, just wondering if this is a known issue? $\endgroup$ Commented May 4, 2014 at 12:33
  • $\begingroup$ Can we have a favicon for it too? $\endgroup$ Commented May 4, 2014 at 13:43
  • 1
    $\begingroup$ @ThomBlairIII Not really an issue per se, the input field needs some sort of trigger to update the kbd preview. CoDEmanX's script below has a little hack for getting around this and is much better. $\endgroup$
    – iKlsR
    Commented May 4, 2014 at 15:48


Since I'm using Autohotkey, I wrote myself a script. Still not tested thoroughly... I'm just using the Unicode symbols, rather than specifying them by Unicode codepoints, so you need to save the script as UTF-8 with BOM, and use Authotokey version supporting UTF-8. As AHK works only on Windows, I didn't include any Mac specific keys. Also I chose glyphs by prioritizing readability rather than being rigorous on their meaning...

There are 3 complex glyphs for Lock keys produced with MathJax - not sure if everyone will see them properly:

$\fbox{A}$ CAPS LOCK $\fbox{1}$ Num Lock $\rlap{\fbox{ ⬇ }} \_\;$ Scroll Lock

Desired result:

Also I don't put mouse hints inside <kbd>, as those aren't keys, but that might be pedantic reasoning; and I don't use images because it would be harder to do and I have mixed feelings about embedding images so aggressively. The script will also add a 3-word description to a mouse indicator:

  • lmb;; $\color{green}{█}\color{#888}{0█}$ left mouse button
  • mmb;; $\color{#888}{█}\color{green}0\color{#888}{█}$ middle mouse button
  • mwu;; $\color{#888}{█}\color{green}⬆\color{#888}{█}$ mouse wheel up
  • mwd;; $\color{#888}{█}\color{green}⬇\color{#888}{█}$ mouse wheel down
  • rmb;; $\color{#888}{█0}\color{green}{█}$ right mouse button


  • for mouse indicators type the strings visible above
  • for keys that produce a visible glyph, type kb then the key (with no modifiers), then two semicolons ;; e.g. kb;;; for ; or kbe;; for E
  • for numpad keys type numpad, then as above, e.g. numpad4;; for Numpad 4
  • kbf1;; to kbf12;; for F1 to F12 keys
  • the rest of special keys by name without kb prefix:

ctrl;;✲ Ctrl ; alt;;⎇ Alt ; shift;;⬆ Shift ; win;;❖ Win ; menu;;☰ Menu ; enter;;↩ Enter ; numpadenter;;Numpad Enter ; tab;;⭾ Tab ; del;;⌦ Del ; ins;;⎀ Ins ; home;;|⬅ Home ; end;;➡| End ; backsp;;⟵ Backspace ; space;;␣ Spacebar ; pgup;;⬆ Page Up ; pgdn;;⬇ Page Down ; prtscr;;⎙ Prt Scr ; capslock;;$\fbox{A}$ CAPS LOCK ; scrolllock;;$\rlap{\fbox{ ⬇ }} \_\;$ Scroll Lock ; numlock;;$\fbox{1}$ Num Lock ; up;;⬆ Up ; left;;⬅ Left ; right;;➡ Right ; down;;⬇ Down

AHK script

Consider adding #if WinActive("ahk_class MozillaWindowClass ahk_exe firefox.exe") as first line so it works only in Firefox.

#Hotstring EndChars . `n `t
#Hotstring NoMouse
#Hotstring c r *
; c - case sensitive
; r - send raw
; * - ending character not required

::lmb;;::$\color{green}{█}\color{#888}{0█}$ *left mouse button*
::mmb;;::$\color{#888}{█}\color{green}0\color{#888}{█}$ *middle mouse button*
::mwu;;::$\color{#888}{█}\color{green}⬆\color{#888}{█}$ *mouse wheel up* 
::mwd;;::$\color{#888}{█}\color{green}⬇\color{#888}{█}$ *mouse wheel down* 
::rmb;;::$\color{#888}{█0}\color{green}{█}$ *right mouse button*

::ctrl;;::<kbd>✲ Ctrl</kbd>
::alt;;::<kbd>⎇ Alt</kbd>
::shift;;::<kbd>⬆ Shift</kbd>
::win;;::<kbd>❖ Win</kbd>
::menu;;::<kbd>☰ Menu</kbd>
::enter;;::<kbd>↩ Enter</kbd>
::tab;;::<kbd>⭾ Tab</kbd>
::del;;::<kbd>⌦ Del</kbd>
::ins;;::<kbd>⎀ Ins</kbd>
::home;;::<kbd>|⬅ Home</kbd>
::end;;::<kbd>➡| End</kbd>
::backsp;;::<kbd>⟵ Backspace</kbd>
::space;;::<kbd>␣ Spacebar</kbd>
::pgup;;::<kbd>⬆ Page Up</kbd>
::pgdn;;::<kbd>⬇ Page Down</kbd>
::prtscr;;::<kbd>⎙ Prt Scr</kbd>
::capslock;;::<kbd>$\fbox{A}$ CAPS LOCK</kbd>
::scrolllock;;::<kbd>$\rlap{\fbox{ ⬇ }} \_\;$ Scroll Lock</kbd> ; <kbd>$\fbox{↕}$ Scroll Lock</kbd>
::numlock;;::<kbd>$\fbox{1}$ Num Lock</kbd>

::numpad0;;::<kbd>Numpad 0</kbd>
::numpad1;;::<kbd>Numpad 1</kbd>
::numpad2;;::<kbd>Numpad 2</kbd>
::numpad3;;::<kbd>Numpad 3</kbd>
::numpad4;;::<kbd>Numpad 4</kbd>
::numpad5;;::<kbd>Numpad 5</kbd>
::numpad6;;::<kbd>Numpad 6</kbd>
::numpad7;;::<kbd>Numpad 7</kbd>
::numpad8;;::<kbd>Numpad 8</kbd>
::numpad9;;::<kbd>Numpad 9</kbd>
::numpad/;;::<kbd>Numpad /</kbd>
::numpad*;;::<kbd>Numpad *</kbd>
::numpad-;;::<kbd>Numpad -</kbd>
::numpad+;;::<kbd>Numpad +</kbd>
::numpadenter;;::<kbd>Numpad Enter</kbd>
::numpad.;;::<kbd>Numpad .</kbd>

::up;;::<kbd>⬆ Up</kbd>
::left;;::<kbd>⬅ Left</kbd>
::right;;::<kbd>➡ Right</kbd>
::down;;::<kbd>⬇ Down</kbd>



You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .