ToolPal
Nahaufnahme einer Computertastatur

JavaScript-Tastaturereignisse erklärt: key, code, keyCode und Debugging

📷 Life Of Pix / Pexels

JavaScript-Tastaturereignisse erklärt: key, code, keyCode und Debugging

Ein praxisorientierter Leitfaden zu JavaScript-Tastaturereignissen — warum keyCode veraltet ist, wie sich key und code unterscheiden und wie man zuverlässige Tastenkombinationen erstellt, die in allen Browsern und Tastaturlayouts funktionieren.

9. April 20268 Min. Lesezeit

Diesen Bug hatte ich mehr als einmal: Ich schreibe einen Tastaturkuerzel-Handler in Chrome, alles funktioniert einwandfrei, ich deploye die Anwendung — und dann kommt ein Fehlerbericht von jemandem mit Firefox. Gleicher Code, anderes Verhalten. Nach einer Stunde Recherche finde ich den Schuldigen: Ich habe e.keyCode verwendet, um die Taste zu erkennen, und es lieferte je nach Browser und Tastaturlayout unterschiedliche Werte.

Dieser Bug ist vollstaendig vermeidbar. Deshalb lohnt es sich, JavaScript-Tastaturereignisse richtig zu verstehen. Dieser Beitrag behandelt das gesamte Tastaturereignismodell — welche Ereignisse ausgeloest werden, welche Eigenschaften man verwenden sollte, welche man vermeiden sollte und wie man Tastenkombinationen erstellt, die wirklich ueberall funktionieren.

Die drei Ereignisse: keydown, keypress, keyup

Wenn ein Benutzer eine Taste drueckt, loest der Browser der Reihe nach bis zu drei Ereignisse aus:

  1. keydown — wird sofort beim Tastendruck ausgeloest, bevor ein Zeichen eingefuegt wird
  2. keypress — wird nach keydown ausgeloest, aber nur fuer Tasten, die einen Zeichenwert erzeugen
  3. keyup — wird ausgeloest, wenn die Taste losgelassen wird

Kurz gesagt: Verwenden Sie fuer die meisten Anwendungsfaelle keydown. Hier ist der Grund:

keypress ist veraltet. Es wurde nie fuer nicht druckende Tasten wie Escape, Delete, F1-F12 oder die Pfeiltasten ausgeloest. Wenn Ihr Shortcut-Handler nur bei Buchstabentasten funktionierte, war keypress vermutlich der Grund. Verwenden Sie es nicht in neuem Code.

keyup ist nuetzlich, wenn Sie erst nach dem Loslassen der Taste reagieren moechten — beispielsweise beim Aktualisieren einer Vorschau nach der Eingabe eines Zeichens. Fuer Tastenkuerzel und Spielsteuerungen bietet keydown jedoch schnelleres und vorhersehbareres Verhalten.

keydown hat ausserdem den Vorteil, dass es beim Gedruechthalten einer Taste im OS-Tastenwiederholrhythmus wiederholt ausgeloest wird — genau das, was man fuer Scrollen oder Spielfigur-Bewegungen benoetigt.

document.addEventListener('keydown', (e) => {
  // Hier sind Sie richtig
  console.log(e.key, e.code);
});

Die wichtigen Eigenschaften

Wenn ein KeyboardEvent ausgeloest wird, enthaelt das Ereignisobjekt zahlreiche Eigenschaften. Hier sind die wesentlichen:

key — Was die Taste produziert

key liefert den Zeichenkettenwert dessen, was die Taste im aktuellen Kontext repraesentiert. Bei einer normalen Buchstabentaste ist es das Zeichen selbst: "a", "A" (mit Shift), "ae" (auf einer deutschen Tastatur mit der AE-Taste). Bei Sondertasten ist es ein beschreibender Name: "Enter", "Escape", "ArrowLeft", "F5", "Backspace".

Dies ist die Eigenschaft, die Sie zuerst verwenden sollten. Sie beruecksichtigt Layout und Modifikatoren und teilt Ihnen mit, was die Taste fuer den Benutzer bedeutet.

document.addEventListener('keydown', (e) => {
  if (e.key === 'Enter') {
    submitForm();
  }
  if (e.key === 'Escape') {
    closeModal();
  }
  if (e.key === 'ArrowLeft') {
    goToPreviousSlide();
  }
});

Ein Hinweis: key unterscheidet Gross-/Kleinschreibung und Modifikatoren. Die Taste a ohne Shift ergibt "a", mit Shift ergibt es "A". Wenn ein Tastenkuerzel nicht von der Gross-/Kleinschreibung abhaengen soll, normalisieren Sie:

if (e.key.toLowerCase() === 'k') {
  openCommandPalette();
}

code — Welche physische Taste gedrueckt wurde

code liefert den Bezeichner fuer die physische Tastenposition, unabhaengig von Modifikatortasten oder Tastaturlayout. Die Taste oben links im Buchstabenbereich ist immer "KeyQ" — auch wenn das Layout des Benutzers dort "A" platziert (wie beim AZERTY-Layout).

Das Format ist einheitlich: Buchstabentasten sind "KeyA" bis "KeyZ", Zifferntasten sind "Digit0" bis "Digit9", Funktionstasten sind "F1" bis "F12".

Verwenden Sie code, wenn Ihnen die physische Position der Taste wichtiger ist als das erzeugte Zeichen. Der klassische Anwendungsfall sind Spielsteuerungen:

document.addEventListener('keydown', (e) => {
  switch (e.code) {
    case 'KeyW':
    case 'ArrowUp':
      player.moveUp();
      break;
    case 'KeyS':
    case 'ArrowDown':
      player.moveDown();
      break;
    case 'KeyA':
    case 'ArrowLeft':
      player.moveLeft();
      break;
    case 'KeyD':
    case 'ArrowRight':
      player.moveRight();
      break;
  }
});

Mit code funktionieren WASD-Steuerungen unabhaengig vom Tastaturlayout des Spielers. Bei AZERTY befindet sich die W-Taste an einer anderen Position, sodass e.key den Wert "z" liefert — aber e.code gibt dennoch "KeyW" zurueck, weil die physische Position dieselbe ist.

keyCode und which — Veraltet, nicht verwenden

keyCode und which sind die alte Methode. Sie liefern einen numerischen Code fuer die Taste — 65 fuer A, 13 fuer Enter, 27 fuer Escape. Das Problem: Diese Werte waren nicht konsistent, insbesondere fuer Satzzeichen und Sondertasten. Verschiedene Browser gaben unterschiedliche Zahlen zurueck, basierend auf Windows Virtual Key Codes ohne intuitive Bedeutung.

Die MDN-Dokumentation markiert sowohl keyCode als auch which als veraltet. Sie existieren noch aus Gruenden der Abwaertskompatibilitaet, sollten aber in neuem Code nicht verwendet werden.

Alter Code, den man noch sieht:

// Nicht so machen
if (e.keyCode === 13) { /* Enter */ }
if (e.which === 27) { /* Escape */ }

Modernes Aequivalent:

// So machen
if (e.key === 'Enter') { /* Enter */ }
if (e.key === 'Escape') { /* Escape */ }

charCode — Nur in keypress, ebenfalls veraltet

charCode war der Unicode-Codepunkt des Zeichens, funktionierte aber nur in keypress-Ereignissen und nur fuer druckbare Zeichen. Da keypress selbst veraltet ist, ist charCode doppelt veraltet. Verwenden Sie einfach e.key und rufen Sie .codePointAt(0) auf, wenn Sie den Unicode-Wert benoetigen.

location — Fuer Tasten an mehreren Positionen

location gibt an, welche Instanz einer Taste gedrueckt wurde, fuer Tasten, die an mehreren Stellen der Tastatur vorhanden sind. Es ist eine Zahl: 0 ist die Standardposition, 1 ist der linke Modifikator, 2 ist der rechte Modifikator und 3 ist der Nummernblock.

e.location === 1 mit e.key === "Shift" bedeutet, dass die linke Shift-Taste gedrueckt wurde. e.location === 3 mit e.key === "5" bedeutet, dass die 5 auf dem Nummernblock gedrueckt wurde.

Modifikatortasten: Ctrl, Shift, Alt, Meta

Fuer Tastenkuerzel kombiniert man in der Regel eine normale Taste mit einer oder mehreren Modifikatortasten. Das Ereignisobjekt hat boolesche Eigenschaften fuer jeden Modifikator:

  • e.ctrlKey — Ctrl ist gedrueckt
  • e.shiftKey — Shift ist gedrueckt
  • e.altKey — Alt (auf dem Mac: Option) ist gedrueckt
  • e.metaKey — Meta ist gedrueckt (auf dem Mac: Command, unter Windows: Windows-Taste)
document.addEventListener('keydown', (e) => {
  // Ctrl+S (auf dem Mac: Cmd+S)
  if ((e.ctrlKey || e.metaKey) && e.key === 's') {
    e.preventDefault(); // Verhindert den Speichern-Dialog des Browsers
    saveDocument();
  }

  // Ctrl+Shift+P — Befehlspalette
  if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'p') {
    e.preventDefault();
    openCommandPalette();
  }

  // Alt+Left — Zurueck
  if (e.altKey && e.key === 'ArrowLeft') {
    goBack();
  }
});

Das Muster e.ctrlKey || e.metaKey ist der Standard-Ansatz fuer plattformubergreifende Tastenkuerzel. Unter macOS verwenden die meisten Tastenkuerzel Command (metaKey), unter Windows/Linux Ctrl. Dieses Muster behandelt beide Faelle.

Das internationale Tastaturproblem

Hier ist ein Szenario, das viele Entwickler erwischt: Ihre App hat ein Tastenkuerzel, zum Beispiel Ctrl+/ zum Umschalten von Kommentaren. Sie testen es auf Ihrer en-US-Tastatur — funktioniert einwandfrei. Dann meldet ein Benutzer in Deutschland einen Bug: das Tastenkuerzel funktioniert nicht.

Auf einem deutschen Tastaturlayout gibt es keine eigene Taste fuer /. Es wird ueber Shift+7 oder eine andere Kombination eingegeben. Daher hat e.key beim Druecken dieser Tastenposition einen vollkommen anderen Wert als erwartet.

Zwei Loesungsansaetze:

Option 1: e.code fuer positionsbasierte Tastenkuerzel verwenden

// Die /-Taste auf einer US-Tastatur liegt an einer bestimmten physischen Position
// code gibt fuer diese Position immer 'Slash' zurueck
if (e.ctrlKey && e.code === 'Slash') {
  toggleComment();
}

Option 2: Benutzern erlauben, eigene Tastenkuerzel zu konfigurieren

Der Ansatz von VS Code — jedes Tastenkuerzel kann nach Belieben neu belegt werden. Mehr Aufwand bei der Implementierung, aber die richtige Antwort fuer ein professionelles Tool mit internationaler Nutzerbasis.

Barrierefreiheit: Tastaturnavigation ist wichtig

Wenn Sie Ihrer App benutzerdefinierte Tastaturinteraktionen hinzufuegen, vergessen Sie nicht, dass Tastaturnavigation eine zentrale Anforderung fuer Barrierefreiheit ist. Benutzer, die auf Screenreader angewiesen sind oder keine Maus verwenden koennen, sind auf Tastaturzugang angewiesen.

Einige Punkte zu beachten:

Fokusverwaltung. Stellen Sie sicher, dass interaktive Elemente fokussierbar sind (bei Bedarf tabindex="0") und dass sich der Fokus beim UI-Wechsel logisch bewegt. Wenn Sie ein Modal oeffnen, verschieben Sie den Fokus hinein. Beim Schliessen zurueck zum ausloesenden Element.

Fokus nicht einsperren (ausser bei Modals). Benutzer sollen mit der Tab-Taste durch die Oberflaeche navigieren koennen, ohne stecken zu bleiben.

Nicht ausschliesslich auf Tastenkuerzel verlassen. Benutzer entdecken sie moeglicherweise nicht. Bieten Sie fuer jede Aktion sichtbare UI-Alternativen an.

Debugging mit dem Keycode Viewer

Beim Entwickeln von Tastaturinteraktionen ist einer der schwierigsten Teile oft herauszufinden, welche Werte der Browser fuer einen bestimmten Tastendruck liefert. Dokumentation ist hilfreich, aber manchmal muss man einfach die Taste druecken und das Ergebnis sehen.

Genau das macht unser Keycode Viewer-Tool. Oeffnen Sie es, druecken Sie eine beliebige Taste, und es zeigt sofort:

  • key — den logischen Wert
  • code — den physischen Positionsbezeichner
  • keyCode — den veralteten numerischen Wert (als Referenz bei der Arbeit mit altem Code)
  • which — die andere veraltete Eigenschaft
  • charCode — den Zeichencode aus keypress-Ereignissen
  • location — Standard/Links/Rechts/Nummernblock
  • ctrlKey, shiftKey, altKey, metaKey — Modifikatorstatus

Besonders nuetzlich bei internationalen Tastaturen, Sonderzeichen oder wenn man herausfinden muss, warum vorhandener Code eine bestimmte Taste nicht erkennt.

Kurzreferenz

EigenschaftVerwenden wennVeraltet?
keyZeichen oder Aktionsname benoetigtNein
codePhysische Tastenposition benoetigtNein
keyCodeNie — nur LegacyJa
whichNie — nur LegacyJa
charCodeNie — nur LegacyJa
ctrlKeyPruefen ob Ctrl gedruecktNein
shiftKeyPruefen ob Shift gedruecktNein
altKeyPruefen ob Alt/Option gedruecktNein
metaKeyPruefen ob Cmd/Win-Taste gedruecktNein

Das wichtigste Denkmodell: Greifen Sie zuerst auf e.key zurueck. Es teilt Ihnen mit, was die Taste bedeutet. Verwenden Sie e.code nur, wenn die physische Position konkret wichtig ist (Spielsteuerungen, layoutunabhaengige Tastenkuerzel). Verwenden Sie keyCode, which oder charCode niemals in neuem Code.

Wer dies beherrscht, erstellt Tastaturinteraktionen, die konsistent ueber alle Browser, Tastaturlayouts und Betriebssysteme hinweg funktionieren. Und Firefox-Fehlerberichte werden der Vergangenheit angehoeren.

Häufig gestellte Fragen

Artikel teilen

XLinkedIn

Verwandte Beiträge