JavaScript Element transitionstart Event

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
DOM event
Instance event

What You’ll Learn

The transitionstart event fires when a CSS transition has actually started—after any transition-delay has ended. Learn how it differs from transitionrun, addEventListener vs ontransitionstart, TransitionEvent properties, and five try-it labs.

01

Kind

Instance event

02

Type

TransitionEvent

03

When

Motion begins

04

Handler

ontransitionstart

05

Cancelable?

No

06

Status

Baseline Widely

Introduction

When the delay is over and property values begin changing, the browser fires transitionstart. Use it to mark UI as “in motion,” start related work that should wait until animation actually begins, or log that the delay window ended.

Earlier in the lifecycle, transitionrun fires when the transition is created (start of any delay). After motion finishes you get transitionend; if it aborts, you get transitioncancel.

💡
Beginner tip

With a positive delay, you will see transitionrun first, then transitionstart when pixels move. With no delay (or a negative delay), MDN says both fire together.

Understanding transitionstart

An instance event on elements that participate in CSS Transitions. MDN: it fires when a CSS transition has actually started, i.e., after any transition-delay has ended. It is not cancelable.

  • Starts when delay ends and the animation of properties begins.
  • TransitionEvent — includes propertyName, elapsedTime, pseudoElement.
  • May be skipped if the transition is canceled during the delay (after transitionrun).
  • Baseline Widely available — solid modern browser support (since Mar 2020).

📝 Syntax

Use the event name with addEventListener, or set the handler property:

JavaScript
addEventListener("transitionstart", (event) => { });

ontransitionstart = (event) => { };

Event type

A TransitionEvent (inherits from Event).

Event properties

PropertyMeaning
propertyNameThe CSS property name associated with the transition
elapsedTimeSeconds the transition had been running when the event fired (not affected by transition-delay)
pseudoElement:: name if the transition runs on a pseudo-element; otherwise ""

⚖️ transitionstart vs related events

EventWhen it firesTypical use
transitionrunTransition is created (start of any delay)Mark “scheduled / pending delay”
transitionstartActual animation begins (end of any delay)Mark UI as “in motion”
transitionendTransition finishes normallyCleanup after success
transitioncancelTransition is aborted earlyCleanup after interrupt

MDN’s key contrast: transitionrun = created / delay starts; transitionstart = delay over, pixels moving.

⚡ Quick Reference

GoalCode
Listenel.addEventListener("transitionstart", fn)
Handler propertyel.ontransitionstart = fn
See start after runUse a positive transition-delay
Read propertyevent.propertyName
Cancelable?No
MDN statusBaseline Widely available

🔍 At a Glance

Four facts to remember about transitionstart.

Event type
TransitionEvent

Property + time

Means
moving

After delay ends

Cancelable
false

Observe only

Baseline
yes

Widely available

Examples Gallery

Examples follow MDN Element: transitionstart event. Try It Yourself labs use a delay so you can see motion begin after transitionrun.

📚 Getting Started

Register handlers the MDN ways when motion actually begins.

Example 1 — addEventListener("transitionstart")

MDN: log when the element has started transitioning.

JavaScript
const element = document.querySelector(".transition");

element.addEventListener("transitionstart", () => {
  console.log("Started transitioning");
});

element.classList.add("grown");
Try It Yourself

How It Works

Adding the driving class creates the transition. With a positive delay, this log appears when the delay finishes and the box starts moving—not at creation time.

Example 2 — ontransitionstart Property

MDN’s alternate style using the event handler property.

JavaScript
const element = document.querySelector(".transition");

element.ontransitionstart = () => {
  console.log("Started transitioning");
};

element.classList.add("grown");
Try It Yourself

How It Works

Same event, different registration API. Prefer addEventListener when you need multiple listeners or easy removal.

📈 Details, Delay Gap & Lifecycle

Read TransitionEvent fields, compare with run, watch the full set.

Example 3 — Read propertyName and elapsedTime

Use TransitionEvent properties for logging or debugging.

JavaScript
const box = document.getElementById("box");

box.addEventListener("transitionstart", (event) => {
  console.log("start:", event.propertyName);
  console.log("elapsedTime:", event.elapsedTime);
  console.log("pseudoElement:", JSON.stringify(event.pseudoElement));
});

box.classList.add("grown");
Try It Yourself

How It Works

At the moment motion begins, elapsedTime is often near 0 (delay does not count toward it). Multiple properties may each produce their own start event.

Example 4 — transitionrun vs transitionstart

With a delay, run fires first; start fires when motion actually begins.

JavaScript
const transition = document.querySelector(".transition");
const message = document.querySelector(".message");

transition.addEventListener("transitionrun", () => {
  message.textContent = "transitionrun fired";
});
transition.addEventListener("transitionstart", () => {
  message.textContent = "transitionstart fired";
});
transition.addEventListener("transitionend", () => {
  message.textContent = "transitionend fired";
});

transition.classList.add("grown");
// CSS: transition-delay: 1s; → run now, start ~1s later
Try It Yourself

How It Works

This is MDN’s core teaching demo: delay makes the gap visible. Cancel during the delay and you may never see transitionstart.

Example 5 — Full Lifecycle Log

Log run, start, cancel, and end together (class toggle with delay).

JavaScript
const el = document.querySelector(".transition");
const message = document.querySelector(".message");
const btn = document.getElementById("toggle");

el.addEventListener("transitionrun", () => {
  message.textContent = "transitionrun fired";
});
el.addEventListener("transitionstart", () => {
  message.textContent = "transitionstart fired";
});
el.addEventListener("transitioncancel", () => {
  message.textContent = "transitioncancel fired";
});
el.addEventListener("transitionend", () => {
  message.textContent = "transitionend fired";
});

btn.addEventListener("click", () => {
  el.classList.toggle("grown");
});
Try It Yourself

How It Works

Toggle on and watch the message flip from run → start → end. That mid-message transitionstart is your “pixels are moving” signal.

🚀 Common Use Cases

  • Marking UI as “animating” only after delay (not during the wait).
  • Starting sound, haptics, or secondary effects when motion begins.
  • Debugging delay timing vs creation (transitionrun).
  • Analytics that count transitions that actually started moving.
  • Teaching the full CSS transition event set with a clear delay gap.

🔧 How It Works

1

Transition is created

transitionrun fires; any transition-delay begins.

Schedule
2

Delay ends

If not canceled during delay, the property animation is ready to begin.

Wait
3

Browser fires transitionstart

A TransitionEvent signals that values are now transitioning.

Event
4

Your handler reacts to motion

Update “in motion” UI, sync effects, then wait for end or cancel.

📝 Notes

  • MDN: Baseline Widely available (since March 2020).
  • Not Deprecated, Experimental, or Non-standard — no status banner required.
  • Not cancelable; observe with addEventListener.
  • May never fire if canceled during delay after transitionrun.
  • Related learning: transitionrun, transitionend, addEventListener(), JavaScript hub.

Browser Support

transitionstart is marked Baseline Widely available on MDN (across browsers since March 2020). Logos use the shared browser-image-sprite.png sprite from this project.

Baseline · Widely available

Element transitionstart

Fires when a CSS transition actually starts after any transition-delay. Not cancelable. Pair with transitionrun to see the delay gap.

Full Widely available
Google Chrome 74+
Yes
Mozilla Firefox 53+
Yes
Apple Safari 13.1+
Yes
Microsoft Edge 79+ Chromium (legacy Edge partial)
Yes
Opera 62+
Yes
Internet Explorer No transitionstart support
Unavailable
transitionstart Baseline

Bottom line: Listen with addEventListener("transitionstart", …). Use a positive delay to separate it from transitionrun; expect start only if the delay was not canceled.

Conclusion

transitionstart is the “motion began” signal—after delay, when property values are changing. Pair it with transitionrun, transitionend, and transitioncancel for a complete lifecycle.

Continue with webkitmouseforcechanged, transitionrun, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Use addEventListener("transitionstart", ...)
  • Use a positive delay when teaching start vs run
  • Use start for “in motion” UI; use run for “scheduled”
  • Log propertyName when several properties transition
  • Keep handlers light—this can fire often on busy UIs

❌ Don’t

  • Assume start always follows run (cancel during delay skips it)
  • Expect only one event when multiple properties transition
  • Forget that zero/negative delay makes run and start fire together
  • Confuse this with CSS Animations / Web Animations APIs
  • Skip transitionend / transitioncancel for cleanup

Key Takeaways

Knowledge Unlocked

Five things to remember about transitionstart

Motion began—after delay ends, pixels are changing.

5
Core concepts
🎨 02

TransitionEvent

property + time

API
⏱️ 03

vs run

delay gap

Compare
🔔 04

addEventListener

preferred

Listen
🎯 05

Baseline

widely available

Compat

❓ Frequently Asked Questions

It fires when a CSS transition has actually started — that is, after any transition-delay has ended and the property values begin changing. It is not cancelable.
No. MDN does not mark Element transitionstart as Deprecated, Experimental, or Non-standard. It is Baseline Widely available (across browsers since March 2020).
transitionrun fires when the transition is created (start of any delay). transitionstart fires when the actual animation begins (end of any delay). With no delay or a negative delay, both fire.
A TransitionEvent. Useful read-only properties include propertyName, elapsedTime, and pseudoElement.
Prefer element.addEventListener("transitionstart", handler). You can also set ontransitionstart where supported.
If the transition is canceled during the delay (after transitionrun), you may never see transitionstart or transitionend — you get transitioncancel instead.
Did you know?

Canceling during the delay can give you transitionrun without transitionstart. That is why “in motion” UI should key off start—not run—when you care about actual animation.

Next: webkitmouseforcechanged

Learn Safari Force Touch pressure-change events.

webkitmouseforcechanged →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful