Keyboard Navigation mit JavaScript
Eine Werkzeugleiste, die die Tastatur versteht
Symbolknöpfe, Zustände, verschachtelter Link: vier Stellen in der Leiste.
Fokus als Zustandswechsel
Eine Taste verändert Fokus, Tabindex und Ansage gemeinsam
Die Werkzeugleiste zeigt den Weg vom Tastendruck bis zum nächsten aktiven Werkzeug.
Roving Tabindex in einer horizontalen Werkzeugleiste
- 1Pfeil rechts
event.keyliefertArrowRight. - 2Index berechnenNach dem letzten Werkzeug beginnt die Reihe wieder vorn.
- 3Tabindex verschiebenAlt erhält
-1, neu erhält0. - 4Fokus setzen
focus()bewegt den sichtbaren Fokusring.
Vorher → nachher
Der Fokus wandert, die Tab-Reihenfolge bleibt kurz
0Kursiv-1Liste-1-1Kursiv0Liste-1Was JavaScript übernimmt
Native button-Elemente liefern Enter und Leertaste bereits mit.
Pfeile, Home und End ändern den aktiven Tabstopp und rufen focus() auf.
Umschalten aktualisiert aria-pressed. Assistive Technik erhält denselben Zustand.
Vollständiges HTML
Drei benannte Umschaltknöpfe
Nur Fett beginnt mit tabindex="0". Die Symbole sind ausgeblendet, weil der zugängliche Name bereits am Knopf steht.
<div class="formatleiste"
role="toolbar"
aria-label="Textformat">
<button type="button" aria-label="Fett"
aria-pressed="false" tabindex="0">
<span aria-hidden="true">B</span>
</button>
<button type="button" aria-label="Kursiv"
aria-pressed="false" tabindex="-1">
<span aria-hidden="true">I</span>
</button>
<button type="button" aria-label="Aufzählung"
aria-pressed="false" tabindex="-1">
<span aria-hidden="true">•</span>
</button>
</div>
<a href="/hilfe/textformat">
Hilfe zum Textformat
</a>Vollständiges JavaScript
Eine Funktion besitzt den Fokuszustand
setzeFokus verteilt den Tabindex und bewegt den DOM-Fokus. Der Klickpfad nutzt dieselbe Funktion, damit Maus und Tastatur denselben Zustand hinterlassen.
const leiste = document.querySelector('.formatleiste');
const werkzeuge = [...leiste.querySelectorAll('button')];
function setzeFokus(ziel) {
werkzeuge.forEach((werkzeug) => {
werkzeug.tabIndex = werkzeug === ziel ? 0 : -1;
});
ziel.focus();
}
leiste.addEventListener('keydown', (event) => {
const aktuell = werkzeuge.indexOf(document.activeElement);
let naechster = aktuell;
switch (event.key) {
case 'ArrowRight':
naechster = (aktuell + 1) % werkzeuge.length;
break;
case 'ArrowLeft':
naechster = (aktuell - 1 + werkzeuge.length)
% werkzeuge.length;
break;
case 'Home':
naechster = 0;
break;
case 'End':
naechster = werkzeuge.length - 1;
break;
default:
return;
}
event.preventDefault();
setzeFokus(werkzeuge[naechster]);
});
leiste.addEventListener('click', (event) => {
if (!(event.target instanceof Element)) return;
const werkzeug = event.target.closest(
'button[aria-pressed]'
);
if (!werkzeug || !leiste.contains(werkzeug)) return;
const aktiv = werkzeug.getAttribute('aria-pressed') === 'true';
werkzeug.setAttribute('aria-pressed', String(!aktiv));
setzeFokus(werkzeug);
});Für normale Seitennavigation brauchen Sie das nicht
Links und einzelne Schaltflächen bleiben in ihrer natürlichen DOM-Reihenfolge. Roving Tabindex gehört zu zusammengesetzten Widgets wie dieser Werkzeugleiste. Positive tabindex-Werte erzeugen eine zweite Reihenfolge und sollten vermieden werden.
Quellen für das Verhalten
So prüfen Sie es
- Drücken Sie Tab bis zur Werkzeugleiste. Genau ein Werkzeug erhält den Fokus.
- Drücken Sie Pfeil rechts und links. Der Fokusring folgt in beide Richtungen.
- Drücken Sie Home und End. Der Fokus springt zum ersten und letzten Werkzeug.
- Drücken Sie Leertaste. Die Ansage wechselt zwischen aktiviert und nicht aktiviert.
- Drücken Sie Tab. Der Fokus verlässt die gesamte Leiste mit einem Tastendruck.
Aus dem Prüfbericht
Vier Befunde an der Werkzeugleiste
Kritisch Die Symbolknöpfe tragen keine Namen Regel button-name
Fett, Kursiv und Liste sind reine Symbole. Ein aria-label benennt das Werkzeug, das der Knopf in der Leiste schaltet.
Kritisch Ein Zustand am falschen Element Regel aria-allowed-attr
Ein aria-checked gehört zu Kontrollkästchen, nicht an einen Umschaltknopf. Für ihn ist aria-pressed der passende Zustand.
Kritisch Der Zustand meldet einen Wert, den es nicht gibt Regel aria-valid-attr-value
aria-pressed nimmt true, false oder mixed. Das Skript setzt den Wert aus derselben Variablen wie die Darstellung.
Kritisch Ein Link steckt im Knopf Regel nested-interactive
Ein Button mit einem Link darin liefert zwei Ziele an einer Stelle. Stellen Sie den Link neben den Knopf.
Zum Mitnehmen
Die Werkzeugleiste, korrigiert
Name, Zustand, Struktur: drei Änderungen an denselben Knöpfen.
Korrektur in 3 Schritten ansehen
Die Symbolknöpfe benennen
Das Symbol bleibt für Vorleseprogramme verborgen. Ein aria-label liefert den Namen des Werkzeugs, das der Knopf schaltet.
KorrekturvergleichSchritt 1 · HTML Vorher
<div role="toolbar" aria-label="Textformat"> <button type="button"> <span aria-hidden="true">B</span> </button> </div>Nachher
<div role="toolbar" aria-label="Textformat"> <button type="button" aria-label="Fett"> <span aria-hidden="true">B</span> </button> </div>Markierte Zeilen wurden geändert
So prüfen Sie es Gehen Sie mit Tab in die Leiste. Ein Vorleseprogramm sagt „Fett, Schaltfläche“.
Den passenden Zustand setzen
aria-pressed beschreibt einen Umschaltknopf mit true oder false. aria-checked gehört zu Kontrollkästchen und Optionsfeldern.
KorrekturvergleichSchritt 2 · HTML Vorher
<button type="button" aria-label="Fett" aria-checked="ja"> <span aria-hidden="true">B</span> </button>Nachher
<button type="button" aria-label="Fett" aria-pressed="false"> <span aria-hidden="true">B</span> </button>Markierte Zeilen wurden geändert
So prüfen Sie es Schalten Sie das Werkzeug ein. Die Ansage wechselt zu „aktiviert“.
Den Link aus dem Knopf holen
Zwei Bedienelemente ineinander ergeben ein unklares Ziel. Nebeneinander behalten Knopf und Link je eigene Rolle und eigenen Namen.
KorrekturvergleichSchritt 3 · HTML Vorher
<button type="button" aria-label="Fett"> <span aria-hidden="true">B</span> <a href="/hilfe/fett">Hilfe</a> </button>Nachher
<button type="button" aria-label="Fett"> <span aria-hidden="true">B</span> </button> <a href="/hilfe/fett">Hilfe zum Fettdruck</a>Markierte Zeilen wurden geändert
So prüfen Sie es Gehen Sie mit Tab durch die Leiste. Knopf und Hilfelink werden einzeln angesagt.
