← All posts

Tutorials

Custom keyboard shortcuts on any page — 4 JavaScript patterns

You spend hours daily in some admin panel that doesn't have Ctrl+S to save, doesn't have Ctrl+Enter to submit, doesn't have / to focus search. Four JS patterns to add your own shortcuts — regardless of what the site author planned.

Pattern 1 — global keydown listener

The basics. Catch keydown on document, check modifiers, execute action:

document.addEventListener('keydown', (e) => {
  // Ctrl+Shift+S → click "Save" button
  if (e.ctrlKey && e.shiftKey && e.key === 'S') {
    e.preventDefault();
    document.querySelector('button[type="submit"]')?.click();
  }

  // Ctrl+/ → focus the search field
  if (e.ctrlKey && e.key === '/') {
    e.preventDefault();
    document.querySelector('input[type="search"], input[name="q"]')?.focus();
  }
});

Key: e.preventDefault() so the browser doesn't run its default shortcut (Ctrl+S = save page). Without it the user gets the HTML save dialog instead of your action.

Pattern 2 — context-aware (only outside inputs)

A single key (e.g. j/k = navigate between elements) cannot fire while the user types in a textarea. Filter by document.activeElement:

function isTyping() {
  const el = document.activeElement;
  if (!el) return false;
  const tag = el.tagName.toLowerCase();
  return tag === 'input' || tag === 'textarea'
    || el.isContentEditable;
}

document.addEventListener('keydown', (e) => {
  if (isTyping()) return;

  // j/k = navigate through list cards (Gmail-style)
  if (e.key === 'j') {
    e.preventDefault();
    document.querySelector('.card.focused')
      ?.nextElementSibling?.classList.add('focused');
  }
});

Without this filter, j typed into a login field would trigger your navigation — meaning the user could never type the email jan@example.com.

Pattern 3 — key sequences (Vim-style)

Some actions deserve two consecutive keys, e.g. gg = scroll to top (like Gmail/GitHub):

let lastKey = null;
let lastKeyTime = 0;
const SEQ_TIMEOUT_MS = 500;

document.addEventListener('keydown', (e) => {
  if (isTyping()) return;
  const now = Date.now();

  // gg → scroll to top
  if (e.key === 'g' && lastKey === 'g' && (now - lastKeyTime) < SEQ_TIMEOUT_MS) {
    window.scrollTo({ top: 0, behavior: 'smooth' });
    lastKey = null;
    return;
  }

  // G (shift+g) → scroll to bottom
  if (e.key === 'G' && e.shiftKey) {
    window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
    return;
  }

  lastKey = e.key;
  lastKeyTime = now;
});

Pattern 4 — help overlay (?)

Shortcuts are useless if you can't remember them. The ? key shows an overlay with your list:

const SHORTCUTS = [
  ['Ctrl+S', 'Save form'],
  ['Ctrl+/', 'Focus search'],
  ['j / k', 'Next / previous card'],
  ['gg', 'Scroll to top'],
  ['G',    'Scroll to bottom'],
];

function showHelp() {
  const overlay = document.createElement('div');
  overlay.style.cssText = `
    position: fixed; inset: 0; background: rgba(0,0,0,.6);
    display: flex; align-items: center; justify-content: center;
    z-index: 999999;
  `;
  overlay.innerHTML = `
    

Shortcuts

${SHORTCUTS.map(([k, v]) => ` `).join('')}
${k} ${v}

Esc or click = close

`; overlay.onclick = () => overlay.remove(); document.body.appendChild(overlay); } document.addEventListener('keydown', (e) => { if (isTyping()) return; if (e.key === '?') { e.preventDefault(); showHelp(); } if (e.key === 'Escape') document.querySelector('div[style*="rgba(0,0,0,.6)"]')?.remove(); });

Pitfalls

How to plug into JustZix

  1. Install JustZix.
  2. Rule per panel: URL pattern https://admin.mycompany.com/*, JavaScript = patterns 1+2+4 from this article.
  3. Sync: the same shortcuts on your laptop and work machine.
  4. Share: send a teammate a share link — they import your shortcuts in one click.

Install JustZix for free and start working at keyboard speed.

Rate this post

No ratings yet — be the first.

Try it yourself

Install JustZix and paste any snippet from this article. Two minutes from zero to a working rule across all your devices.

Get JustZix

Features · How it works · Examples · Use cases