Signatur
Beschreibung
FocusEvent ist die Ereignis-Schnittstelle für alle Fokuswechsel im DOM. Wenn ein Element den Tastatur-Fokus erhält oder verliert, erzeugt der Browser Ereignisse dieses Typs: focus und focusin beim Erhalten, blur und focusout beim Verlieren des Fokus. Die Schnittstelle erbt von UIEvent und damit von Event.
Der wichtigste Unterschied zwischen den Ereignispaaren: focus und blur steigen nicht auf (bubbling), focusin und focusout dagegen schon. Wer Fokuswechsel zentral an einem Container überwachen möchte (Ereignis-Delegation, z. B. für ein ganzes Formular), sollte daher focusin/focusout verwenden oder bei focus/blur die Capture-Phase nutzen.
Die einzige eigene Eigenschaft ist relatedTarget: Bei blur/focusout ist es das Element, das den Fokus erhält, bei focus/focusin das Element, das den Fokus verliert. Damit lässt sich z. B. prüfen, ob der Fokus einen Komponentenbereich (Dropdown, Dialog, Menü) wirklich verlässt oder nur innerhalb davon wandert.
Mit dem Konstruktor new FocusEvent(type, options) lassen sich synthetische Fokus-Ereignisse erzeugen, etwa für Tests. Solche Ereignisse verschieben den tatsächlichen Fokus aber nicht – dafür ist HTMLElement.prototype.focus() zuständig.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Ereignisses, typischerweise "focus", "blur", "focusin" oder "focusout" (Konstruktor). |
|
| $options | FocusEventInit | {} | Optionales Objekt mit den Feldern aus UIEventInit (bubbles, cancelable, composed, view, detail) sowie relatedTarget (EventTarget | null, Standard null). |
| $relatedTarget | EventTarget | null | null | Instanz-Eigenschaft (schreibgeschützt): das sekundäre Ziel des Fokuswechsels. null, wenn kein solches Element existiert (z. B. Fokus wechselt in ein anderes Fenster) oder aus Sicherheitsgründen verborgen wird. |
Rückgabewert
FocusEvent-Instanz; in Event-Handlern wird sie als Ereignisobjekt übergeben.Beispiele
Fokus und Verlassen eines Eingabefelds behandeln
const input = document.querySelector('#email');
const onFocus = (event) => {
event.target.classList.add('aktiv');
console.log('Fokus erhalten, vorher:', event.relatedTarget?.id ?? 'nichts');
};
const onBlur = (event) => {
event.target.classList.remove('aktiv');
if (!event.target.value.includes('@')) {
console.log('Bitte gültige E-Mail eingeben');
}
};
input.addEventListener('focus', onFocus);
input.addEventListener('blur', onBlur);
// Alternativ über die on-Property:
// input.onfocus = onFocus;
// Später wieder entfernen:
// input.removeEventListener('focus', onFocus);
Ereignis-Delegation mit focusin/focusout am Formular
const form = document.querySelector('#kontakt');
// focusin/focusout steigen auf – ein Listener genügt für alle Felder
form.addEventListener('focusin', (event) => {
event.target.closest('.feld')?.classList.add('hervorgehoben');
});
form.addEventListener('focusout', (event) => {
event.target.closest('.feld')?.classList.remove('hervorgehoben');
});
Dropdown schließen, wenn der Fokus die Komponente verlässt
const menu = document.querySelector('.dropdown');
menu.addEventListener('focusout', (event) => {
// relatedTarget = Element, das den Fokus als Nächstes erhält
const next = event.relatedTarget;
if (!next || !menu.contains(next)) {
menu.classList.remove('offen');
console.log('Dropdown geschlossen');
}
});
Synthetisches FocusEvent erzeugen (z. B. im Test)
const field = document.createElement('input');
document.body.append(field);
field.addEventListener('focusin', (e) => {
console.log(e instanceof FocusEvent, e.type, e.bubbles, e.relatedTarget);
});
const evt = new FocusEvent('focusin', { bubbles: true, relatedTarget: null });
field.dispatchEvent(evt);
console.log(document.activeElement === field);
// Wichtig · Fallstricke
- Bubbling:
focusundblursteigen nicht auf. Für Delegationfocusin/focusoutnutzen oderaddEventListener('focus', fn, true)(Capture). - Reihenfolge (laut Spezifikation und in aktuellen Browsern):
blur→focusout→focus→focusin. Ältere Browser wichen teilweise ab – nicht auf eine exakte Reihenfolge zwischen verschiedenen Elementen verlassen. relatedTargetist oftnull: wenn der Fokus das Dokument/Fenster verlässt, auf ein nicht fokussierbares Element geklickt wird oder das Ziel in einem anderen Ursprung (iframe) liegt. Safari auf macOS fokussiert Buttons beim Klick standardmäßig nicht, daher istrelatedTargetdort bei Klicks auf<button>häufignull.- Während
blur/focusoutzeigtdocument.activeElementmeist schon aufbody, noch nicht auf das neue Element. Wer das neue Element braucht, nutztrelatedTargetoder wartet perrequestAnimationFrame/setTimeout. - Fokus-Ereignisse sind nicht abbrechbar;
preventDefault()verhindert den Fokuswechsel nicht. Um Fokus beim Klicken zu verhindern,mousedown/pointerdownabbrechen. - Mit
dispatchEvent()ausgelöste Ereignisse habenisTrusted === falseund ändern den echten Fokus nicht. - Barrierefreiheit: Fokus nicht in
blur-Handlern „zurückzwingen“ (Fokusfalle), außer in modalen Dialogen mit klarer Schließmöglichkeit.