Signatur
Beschreibung
Das Ereignis focusin wird ausgelöst, sobald ein Element den Fokus erhalten hat. Es folgt unmittelbar auf das Ereignis focus. Der entscheidende Unterschied: focusin steigt im DOM auf (Bubbling), focus dagegen nicht. Das Ereignis ist ein FocusEvent und lässt sich nicht abbrechen.
Deshalb eignet sich focusin besonders gut für Event-Delegation: Ein einziger Listener auf einem Formular, einer Toolbar oder einem Dialog erfährt, welches Kindelement gerade den Fokus bekommen hat. Typische Anwendungen sind das Hervorheben aktiver Formulargruppen, Fokus-Tracking für die Barrierefreiheit, Roving-Tabindex-Muster oder das Anzeigen kontextbezogener Hilfetexte.
Über event.target erhält man das Element, das den Fokus bekommen hat, und über event.relatedTarget das Element, das ihn verloren hat (oder null). Das Gegenstück ist focusout. Anders als bei focus gibt es für focusin keine onfocusin-Eigenschaft in den Browsern; man registriert den Handler daher mit addEventListener.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "focusin". |
|
| $handler Pflicht | (event: FocusEvent) => void | Callback, das ein FocusEvent erhält. Wichtige Eigenschaften: target (bekommt den Fokus), relatedTarget (verliert den Fokus bzw. null). |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie capture, once, passive oder signal (zum Entfernen per AbortController). |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler erhält ein FocusEvent mit bubbles: true und cancelable: false.Beispiele
Aktives Formularfeld per Delegation hervorheben
const form = document.querySelector('#kontakt');
// Ein Listener für alle Felder – funktioniert dank Bubbling
form.addEventListener('focusin', (event) => {
const gruppe = event.target.closest('.feldgruppe');
gruppe?.classList.add('aktiv');
console.log(`Fokus auf: ${event.target.name}`);
});
form.addEventListener('focusout', (event) => {
event.target.closest('.feldgruppe')?.classList.remove('aktiv');
});
Fokuswechsel mit relatedTarget protokollieren
document.addEventListener('focusin', (event) => {
const von = event.relatedTarget?.id || '(nichts)';
const nach = event.target.id || event.target.tagName;
console.log(`Fokus: ${von} → ${nach}`);
});
Listener wieder entfernen (removeEventListener und AbortController)
const toolbar = document.querySelector('[role="toolbar"]');
const onFocusIn = (event) => {
// Roving Tabindex: nur das fokussierte Element ist per Tab erreichbar
toolbar.querySelectorAll('button').forEach((btn) => {
btn.tabIndex = btn === event.target ? 0 : -1;
});
};
toolbar.addEventListener('focusin', onFocusIn);
// Später wieder entfernen:
toolbar.removeEventListener('focusin', onFocusIn);
// Alternative mit AbortController
const controller = new AbortController();
toolbar.addEventListener('focusin', onFocusIn, { signal: controller.signal });
controller.abort(); // entfernt den Listener
// Wichtig · Fallstricke
- Keine
onfocusin-Eigenschaft:element.onfocusin = …funktioniert in den Browsern nicht zuverlässig. VerwendeaddEventListener. - Reihenfolge beim Fokuswechsel von A nach B:
blur(A) →focusout(A) →focus(B) →focusin(B). Ältere Spezifikationen und manche alten Browser verwendeten eine andere Reihenfolge; verlasse dich nicht zu stark darauf. - Alternative ohne
focusin:focusmit{ capture: true }erreicht ebenfalls den Elternknoten, allerdings in der Capture-Phase. relatedTargetistnull, wenn der Fokus von außerhalb des Dokuments kommt (z. B. aus einem anderen Fenster) oder wenn das vorherige Element nicht fokussierbar war.- Ein programmatischer Aufruf von
element.focus()löstfocusinebenfalls aus. Wer darin erneut den Fokus verschiebt, riskiert Endlosschleifen. - Bei Shadow DOM wird
event.targetauf den Host umgeleitet (Retargeting). Das tatsächlich fokussierte Element findest du überevent.composedPath()[0]. - Kompatibilität: wird von allen modernen Browsern unterstützt. Firefox kennt das Ereignis erst ab Version 52.