Signatur
Beschreibung
Das Ereignis transitionrun tritt ein, wenn für ein Element ein CSS-Übergang (transition) angelegt wird. Das passiert, sobald sich eine animierbare Eigenschaft ändert, für die ein Übergang definiert ist. Der Zeitpunkt liegt vor einer mit transition-delay festgelegten Verzögerung. Deshalb unterscheidet es sich von transitionstart, das erst nach Ablauf der Verzögerung feuert, wenn die Animation tatsächlich losläuft.
Registrieren lässt sich das Ereignis per element.addEventListener("transitionrun", handler) oder über die Eigenschaft element.ontransitionrun = handler. Der Handler bekommt ein TransitionEvent mit den Eigenschaften propertyName, elapsedTime und pseudoElement. Das Ereignis steigt im DOM auf (bubbles) und lässt sich nicht abbrechen (nicht cancelable).
Typische Einsatzfälle sind Zustände, die sofort beim Auslösen gelten sollen, auch wenn die sichtbare Animation noch wartet. Beispiele: Schaltflächen sperren, eine CSS-Klasse wie is-animating setzen, Protokoll oder Analyse starten. Zusammen mit transitionstart, transitionend und transitioncancel lässt sich der komplette Ablauf eines Übergangs verfolgen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "transitionrun". |
|
| $handler Pflicht | (event: TransitionEvent) => void | Callback, der ein TransitionEvent erhält. Wichtige Eigenschaften: propertyName (z. B. "opacity"), elapsedTime (Sekunden, bei transitionrun normalerweise 0, außer bei negativem Delay) und pseudoElement (z. B. "::before" oder ""). |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once, capture, passive oder signal zum späteren Entfernen. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler bekommt ein TransitionEvent-Objekt.Beispiele
transitionrun vs. transitionstart bei Verzögerung
// CSS: .box { transition: transform 1s ease 500ms; } .box.moved { transform: translateX(200px); }
const box = document.querySelector('.box');
box.addEventListener('transitionrun', (e) => {
console.log(`run: ${e.propertyName} (${performance.now().toFixed(0)} ms)`);
});
box.addEventListener('transitionstart', (e) => {
console.log(`start: ${e.propertyName} (${performance.now().toFixed(0)} ms)`);
});
box.addEventListener('transitionend', (e) => {
console.log(`end: ${e.propertyName}`);
});
box.classList.add('moved');
Button während der Animation sperren (on-Property)
// CSS: .panel { transition: height 400ms 200ms; }
const panel = document.querySelector('.panel');
const toggle = document.querySelector('#toggle');
// Sperren schon beim Anlegen, nicht erst nach dem Delay
panel.ontransitionrun = () => {
toggle.disabled = true;
};
const unlock = () => { toggle.disabled = false; };
panel.ontransitionend = unlock;
panel.ontransitioncancel = unlock;
toggle.addEventListener('click', () => panel.classList.toggle('open'));
Listener mit AbortController wieder entfernen
const card = document.querySelector('.card');
const controller = new AbortController();
const onRun = (e) => {
// Nur auf die eigene opacity-Transition reagieren, nicht auf aufsteigende Ereignisse von Kindelementen
if (e.target !== card || e.propertyName !== 'opacity') return;
card.classList.add('is-animating');
console.log('Fade angelegt, pseudoElement:', JSON.stringify(e.pseudoElement));
};
card.addEventListener('transitionrun', onRun, { signal: controller.signal });
// Später: alle damit registrierten Listener entfernen
// controller.abort();
// Alternativ: card.removeEventListener('transitionrun', onRun);
// Wichtig · Fallstricke
- Ein Ereignis pro Eigenschaft: Bei
transition: alloder mehreren Eigenschaften feuerttransitionrunfür jede animierte Eigenschaft einzeln. Filtern Sie deshalb übere.propertyName. Kurzschreibweisen wiepaddingwerden in Einzeleigenschaften wiepadding-topusw. zerlegt. - Aufsteigen (Bubbling): Übergänge von Kindelementen lösen den Handler am Elternelement ebenfalls aus. Prüfen Sie
e.target === element. - Kein Ereignis ohne Übergang: Ändert sich der Wert nicht, ist die Dauer
0soder die Eigenschaft nicht animierbar, wird kein Übergang angelegt und es kommt kein Ereignis. Das Gleiche gilt, wenn der Stil vor dem nächsten Style-Recalc zweimal geändert wird. - Abbruch: Wird der Übergang abgebrochen, bevor er fertig ist (z. B. durch Entfernen der Klasse,
display: noneoder das Entfernen des Elements), folgttransitioncancelstatttransitionend. Ohne Verzögerung feuerntransitionrunundtransitionstartpraktisch gleichzeitig. - Kompatibilität: Unterstützt in Chrome/Edge 74+, Firefox 53+ und Safari 13.1+. Sehr alte WebKit-Versionen kennen das Ereignis nicht, Präfix-Varianten gibt es dafür nicht.
- Bei
prefers-reduced-motionentfernen viele Stylesheets die Übergänge. Dann fehlt das Ereignis, und Logik, die sich darauf verlässt, braucht einen Rückfallweg.