Signatur
Beschreibung
Das Ereignis transitionend feuert, wenn ein CSS-Übergang am Element vollständig durchgelaufen ist. Das heißt: Die in transition-duration und transition-delay festgelegte Zeit ist vorbei und die Eigenschaft hat ihren Zielwert erreicht. Registrieren kann man es mit element.addEventListener("transitionend", handler) oder über die Eigenschaft element.ontransitionend = handler. Der Handler bekommt ein TransitionEvent.
Typische Einsätze sind Aufräumarbeiten nach einer Animation: ein Element nach dem Ausblenden mit display: none verstecken oder aus dem DOM entfernen, CSS-Klassen zurücksetzen, den Fokus verschieben oder mehrere Animationsschritte nacheinander ausführen. So muss man die Dauer nicht zusätzlich mit setTimeout im JavaScript nachbauen.
Wichtig: Das Ereignis feuert einmal pro übergehender CSS-Eigenschaft. Geht zum Beispiel transition: all über opacity und transform, kommt es zweimal. Mit event.propertyName filtert man die gewünschte Eigenschaft heraus. Weitere nützliche Eigenschaften sind event.elapsedTime (Laufzeit in Sekunden, ohne Verzögerung) und event.pseudoElement (z. B. "::before", sonst leerer String).
Das Ereignis steigt im DOM auf (bubbles) und lässt sich abbrechen (cancelable). Ein Handler am Elternelement bekommt also auch die Übergänge der Kindelemente mit. Mit event.target prüft man deshalb, ob der Übergang wirklich am gewünschten Element stattfand.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "transitionend". |
|
| $handler Pflicht | (event: TransitionEvent) => void | Callback, der ein TransitionEvent mit propertyName, elapsedTime und pseudoElement bekommt. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie { once: true }, capture oder signal zum Entfernen per AbortController. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler bekommt ein TransitionEvent.Beispiele
Element ausblenden und danach entfernen
// CSS: .toast { transition: opacity 0.3s; } .toast.hide { opacity: 0; }
const toast = document.querySelector('.toast');
const onEnd = (event) => {
if (event.target !== toast || event.propertyName !== 'opacity') return;
toast.removeEventListener('transitionend', onEnd);
toast.remove();
console.log(`Entfernt nach ${event.elapsedTime}s`);
};
toast.addEventListener('transitionend', onEnd);
toast.classList.add('hide');
Übergang als Promise abwarten
const waitForTransition = (el, property) =>
new Promise((resolve) => {
const handler = (event) => {
if (event.target === el && event.propertyName === property) {
el.removeEventListener('transitionend', handler);
resolve(event);
}
};
el.addEventListener('transitionend', handler);
});
const panel = document.querySelector('#panel');
const openPanel = async () => {
panel.classList.add('open'); // CSS: #panel.open { transform: translateX(0); }
await waitForTransition(panel, 'transform');
panel.querySelector('input')?.focus();
console.log('Panel geöffnet');
};
openPanel();
Alternative über die on-Eigenschaft
const box = document.querySelector('.box');
box.ontransitionend = (event) => {
console.log(`${event.propertyName} fertig${event.pseudoElement ? ' an ' + event.pseudoElement : ''}`);
};
box.style.transition = 'width 0.5s, background-color 0.5s';
box.style.width = '300px';
box.style.backgroundColor = 'tomato';
// Handler später wieder entfernen:
// box.ontransitionend = null;
// Wichtig · Fallstricke
- Wird der Übergang abgebrochen, feuert das Ereignis nicht. Das passiert, wenn die Eigenschaft vorher entfernt oder zurückgesetzt wird, wenn das Element
display: nonebekommt oder aus dem DOM entfernt wird. Stattdessen kommttransitioncancel. Wenn man sich auftransitionendverlässt, sollte mantransitioncancelebenfalls behandeln oder mit einemsetTimeoutabsichern. Sonst wartet ein Promise womöglich für immer. - Ändert sich der Wert gar nicht, gilt
transition-duration: 0soder stehtprefers-reduced-motionauf0s, startet kein Übergang. Dann kommt auch kein Ereignis. - Bei Kurzformen wie
paddingoderborderfeuert das Ereignis pro Einzeleigenschaft, z. B.padding-leftundpadding-top.propertyNameenthält also nie die Kurzform. - Da das Ereignis aufsteigt, feuern auch Übergänge von Kindelementen. Prüfen Sie deshalb
event.target. - Kompatibilität: Alle modernen Browser unterstützen das Ereignis ohne Präfix. Das alte
webkitTransitionEndbraucht man nur noch für sehr alte WebKit-Versionen.ontransitionendist in allen aktuellen Browsern verfügbar. - Für Animationen mit
@keyframesgibt es stattdessenanimationend.