JavaScript focus visible
Fokus setzen und die Markierung zeigen
Fehlermeldung, Dialog, Sprungziel: drei Stellen, an denen Skripte fokussieren.
Fokus-Choreografie
JavaScript bestimmt die Landung. CSS zeigt sie.
Fokuspunkt, sichtbarer Rahmen und Scrollposition sind drei getrennte Entscheidungen.
Fehler erklären
Vom Absenden zur Meldung vor dem Feld.
fehler.focus()Scrollen: BrowserDialog betreten
Vom Öffner zum Titel und wieder zurück.
titel.focus({ preventScroll: true })Scrollen: ausZum Inhalt springen
Vom Kopf zum weit entfernten Hauptbereich.
inhalt.focus()Scrollen: Browserfocus() setzt document.activeElement
Das Skript wählt das Ziel und entscheidet, ob der Browser dorthin scrollt.
:focus oder :focus-visible zeichnet den Rahmen
Die Pseudoklasse ändert keine Fokusposition. Sie macht den Zustand nur sichtbar.
Scrollentscheidung
Das Ziel bestimmt die Option
Ohne Option scrollt focus() das Ziel in den sichtbaren Bereich. Verwenden Sie preventScroll: true, wenn die Ebene bereits im Blick liegt oder ein eigener Scrollschritt folgt.
focus()Fokus + Scrollenfocus({ preventScroll: true })Fokus, Ausschnitt bleibtFehlerzusammenfassung
Die Meldung wird sichtbar, erhält den Fokus und darf in den Bildausschnitt rücken. :focus zeigt die Landung auch nach einem Zeigerklick.
<form id="konto" novalidate>
<p id="mail-fehler" tabindex="-1" hidden>
Bitte tragen Sie eine E-Mail-Adresse ein.
</p>
<label for="mail">E-Mail-Adresse</label>
<input id="mail" type="email" required>
<button type="submit">Konto anlegen</button>
</form>
<style>
#mail-fehler:focus {
outline: 3px solid #3b2bbd;
outline-offset: 3px;
}
</style>
const form = document.querySelector('#konto');
const mail = document.querySelector('#mail');
const fehler = document.querySelector('#mail-fehler');
form.addEventListener('submit', (event) => {
if (mail.validity.valid) return;
event.preventDefault();
fehler.hidden = false;
fehler.focus();
});Modaldialog
Der Titel erklärt den Kontext. Beim Schließen geht der Fokus zum Öffner zurück. Beide Ziele liegen im Blick, deshalb bleibt der Bildausschnitt stehen.
<button id="oeffnen" type="button">Warenkorb</button>
<dialog id="dialog" aria-labelledby="dialog-titel">
<h2 id="dialog-titel" tabindex="-1">Bestellung prüfen</h2>
<button id="schliessen" type="button">Schließen</button>
</dialog>
const dialog = document.querySelector('#dialog');
const titel = document.querySelector('#dialog-titel');
const oeffnen = document.querySelector('#oeffnen');
const schliessen = document.querySelector('#schliessen');
oeffnen.addEventListener('click', () => {
dialog.showModal();
titel.focus({ preventScroll: true });
});
schliessen.addEventListener('click', () => dialog.close());
dialog.addEventListener('close', () => {
oeffnen.focus({ preventScroll: true });
});Sprungziel
Der Link aktualisiert das Fragment. Im nächsten Frame übernimmt der Hauptbereich den Fokus. Ohne preventScroll kommt das entfernte Ziel ins Bild.
<a id="sprung" href="#inhalt">Zum Inhalt</a>
<nav aria-label="Hauptnavigation">…</nav>
<main id="inhalt" tabindex="-1">
<h1>Seitentitel</h1>
</main>
const sprung = document.querySelector('#sprung');
const inhalt = document.querySelector('#inhalt');
sprung.addEventListener('click', () => {
requestAnimationFrame(() => inhalt.focus());
});So prüfen Sie es
Beobachten Sie Fokus, Rahmen und Scrollposition getrennt
- FokuspunktLesen Sie nach jeder Aktion
document.activeElementaus. - MarkierungLösen Sie jeden Weg mit Tastatur und Zeiger aus. Das Ziel bleibt erkennbar.
- AusschnittDas Ziel liegt vollständig im Bild; kein unnötiger Sprung bewegt den Hintergrund.
- WeiterwegTab führt vom neuen Fokus logisch weiter, Escape oder Schließen führt zurück.
Aus dem Prüfbericht
Ein Befund am Fokusziel
Zum Mitnehmen
Der Fokussprung, korrigiert
focus() bewegt den Fokus, CSS zeigt ihn, ARIA darf ihn nicht verstecken.
Korrektur in 3 Schritten ansehen
Die Ausblendung am Container entfernen
Ein Bereich mit aria-hidden bleibt sichtbar und anspringbar, aber stumm. Als Ziel eines Fokussprungs gehört das Attribut weg.
KorrekturvergleichSchritt 1 · HTML Vorher
<div id="formular-fehler" aria-hidden="true" tabindex="-1"> <p>Bitte tragen Sie eine E-Mail-Adresse ein.</p> </div>Nachher
<div id="formular-fehler" tabindex="-1"> <p>Bitte tragen Sie eine E-Mail-Adresse ein.</p> </div>Markierte Zeilen wurden geändert
So prüfen Sie es Senden Sie das Formular leer ab. Ein Vorleseprogramm liest die Fehlermeldung vor.
Den Fokus im Skript setzen
Das Attribut tabindex mit minus eins macht den Textblock per Skript fokussierbar, ohne ihn in den Tab-Weg zu stellen.
KorrekturvergleichSchritt 2 · JavaScript Vorher
formular.addEventListener('submit', (ereignis) => { ereignis.preventDefault(); fehler.hidden = false; });Nachher
formular.addEventListener('submit', (ereignis) => { ereignis.preventDefault(); fehler.hidden = false; fehler.focus(); });Markierte Zeilen wurden geändert
So prüfen Sie es Senden Sie leer ab und drücken Sie Tab. Es geht bei der Meldung weiter, nicht am Seitenanfang.
Die Markierung sichtbar halten
Bei Tastaturbedienung zeigt focus-visible den Rahmen. Ein per Skript fokussiertes Meldungsziel markieren Sie mit focus auch nach einem Zeigerklick.
KorrekturvergleichSchritt 3 · CSS Vorher
#formular-fehler:focus { outline: none; }Nachher
#formular-fehler:focus { outline: 3px solid #3b2bbd; outline-offset: 3px; }Markierte Zeilen wurden geändert
So prüfen Sie es Lösen Sie den Fehler mit Tastatur und Zeiger aus. Ein Rahmen umschließt die Meldung.
