keydown on document, modifier keys & focus

Keyboard shortcuts

Lesson 18 of 20 · 12 min · Module 5: Smoother interactions

Shortcuts make frequent actions fast: / to search on many sites, j and k to move through a list. Done carelessly, they also hijack typing and clash with the browser’s own keys.

Start this lesson →

Free. No installation: you write and run the code in your browser, and it is checked automatically.

By the end, you’ll be able to…

  • Handle page-wide keys with a keydown listener on document
  • Keep shortcuts away from typing and browser shortcuts
  • Prevent the default only for keys you handle

The idea

Listen for keydown on document and check event.key. Ignore keys typed into text fields, which you can detect with event.target.closest('input, textarea'), and keys pressed together with Ctrl, ⌘ or Alt, which belong to the browser and the system. Call event.preventDefault() only for the keys you actually handle.

document.addEventListener('keydown', event => {
  if (event.key === '?' && !event.target.closest('input, textarea')) {
    console.log('Show the list of shortcuts');
  }
});

01Listen on the whole document

Key events start at the focused element, or at the body when nothing is focused, and bubble up to document. One listener there sees every key press on the page, which is exactly what page-wide shortcuts need.

02Shortcuts must not steal typing

If j moved the highlight while someone typed “javascript” into the search box, the box would be unusable. Checking event.target first, and skipping text fields, solves it. Escape is the useful exception: it lets people leave the box without the mouse.

const typing = event.target.closest('input, textarea, select, [contenteditable]');
if (typing) return;

03Leave the system alone

Ctrl + F, ⌘ + L and Alt + ← belong to the browser and the operating system, so return early when a modifier is pressed. Document your shortcuts on the page, and offer a way to turn single-key shortcuts off: accessibility guidelines ask for it, because people using speech input can trigger them by accident.

Your turn

Complete the keydown listener on document: 1) do nothing when ctrlKey, metaKey or altKey is set; 2) Escape in #search clears it and leaves it with blur(); 3) leave every other key typed in a text field alone; 4) / prevents the default and focuses #search; 5) j and k move the highlight to the next and the previous lesson, stopping at the first and the last one, and call render().

What the checks look for

  • The first lesson starts highlighted
  • / jumps to the search box
  • j and k move the highlight
  • The highlight stops at both ends
  • Typing in the search box is never a shortcut
  • Escape clears and leaves the search box
  • Ctrl, ⌘ and Alt combinations are left to the browser
Try it in the editor →

Take this with you

Check modifiers and focus first, then handle only the keys you own.

Go a little further

Add ? to show and hide a list of the shortcuts, and a checkbox that turns the single-key shortcuts off.

Learn JavaScript in the Browser for free

20 short lessons with real code and instant checks.

See the whole course →