JavaScript Element animationend Event

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

What You’ll Learn

The animationend event fires when a CSS Animation completes. Learn addEventListener vs onanimationend, AnimationEvent properties, how it differs from animationcancel, and how to clean up classes after a normal finish—with five examples and try-it labs.

01

Kind

Instance event

02

Type

AnimationEvent

03

When

Animation completed

04

Handler

onanimationend

05

Pair with

animationcancel

06

Status

Baseline widely available

Introduction

When a CSS animation runs all the way through its planned duration and iterations, the browser fires animationend. That is your signal to remove a temporary class, reveal the next UI step, or start another animation.

MDN: if the animation aborts before completion—for example the element is removed from the DOM, or the animation is removed from the element— animationend is not fired. Use animationcancel for those interrupt cases (where supported).

💡
Beginner tip

Prefer addEventListener("animationend", ...) so you can attach multiple handlers and remove them cleanly. The onanimationend property is fine for quick demos.

Understanding animationend

An instance event on elements that finish a CSS Animation. It answers: “Did this animation complete normally?”

  • Fires when the animation completes (after the last iteration).
  • Does not fire if the animation is aborted early.
  • AnimationEvent — includes animationName, elapsedTime, pseudoElement.
  • Baseline Widely available on MDN (since December 2019).

📝 Syntax

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

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

onanimationend = (event) => { };

Event type

An AnimationEvent (inherits from Event).

Event properties

PropertyMeaning
animationNameThe animation-name that generated the animation
elapsedTimeSeconds the animation had been running when this event fired (paused time excluded)
pseudoElement:: name if animated on a pseudo-element; otherwise ""

⚖️ Animation lifecycle events

EventWhen it firesTypical use
animationstartAnimation beginsMark UI as “playing”
animationiterationEach iteration ends (except the last)Count loops
animationendAnimation finishes normallyCleanup after success
animationcancelAnimation aborts earlyCleanup after interrupt

⚡ Quick Reference

GoalCode
Listenel.addEventListener("animationend", fn)
Handler propertyel.onanimationend = fn
Read nameevent.animationName
Read timeevent.elapsedTime
Cleanup classRemove animating class inside the handler
Aborted pathListen for animationcancel too
MDN statusBaseline Widely available (Dec 2019)

🔍 At a Glance

Four facts to remember about animationend.

Event type
AnimationEvent

Name + time

Means
completed

Normal finish

If aborted
no fire

Use cancel

Baseline
yes

Widely available

Examples Gallery

Examples follow MDN Element: animationend event. Try It Yourself labs run a short CSS animation so you can watch animationend fire when it finishes.

📚 Getting Started

Register handlers the MDN ways.

Example 1 — addEventListener("animationend")

MDN: listen on an animating element and log when the animation completes.

JavaScript
const animated = document.querySelector(".animated");

animated.addEventListener("animationend", () => {
  console.log("Animation ended");
});

// Make sure .animated has a CSS animation that can finish
// (finite duration / iteration-count, not infinite).
Try It Yourself

How It Works

After the last iteration finishes, the browser dispatches animationend. Infinite animations never reach this event unless you stop them another way (which may cancel instead of end).

Example 2 — onanimationend Property

MDN’s alternate style using the event handler property.

JavaScript
const animated = document.querySelector(".animated");

animated.onanimationend = () => {
  console.log("Animation ended");
};

// Assigning again replaces the previous onanimationend handler.
Try It Yourself

How It Works

Same event, different registration API. Prefer addEventListener when you need more than one handler.

📈 Details, Cleanup & Lifecycle

Read AnimationEvent fields, remove classes, watch the full set.

Example 3 — Read animationName and elapsedTime

Use AnimationEvent properties for logging or branching when several animations share a node.

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

box.addEventListener("animationend", (event) => {
  console.log("ended:", event.animationName);
  console.log("elapsedTime:", event.elapsedTime);
  console.log("pseudoElement:", JSON.stringify(event.pseudoElement));
});

box.classList.add("fade-in");
Try It Yourself

How It Works

elapsedTime reports how long the animation had been running (in seconds) when it ended—excluding paused time.

Example 4 — Remove the Animating Class on End

Common UI pattern: add a class to play once, then remove it in animationend.

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

box.addEventListener("animationend", () => {
  box.classList.remove("bounce");
  console.log("Class removed after animationend");
});

btn.addEventListener("click", () => {
  box.classList.add("bounce");
});
Try It Yourself

How It Works

Removing the class after completion lets you replay the animation later by adding the class again. If you leave it on, a second click may not restart the same animation.

Example 5 — Full Lifecycle Log

Inspired by MDN’s live example: log start, iteration, end, and cancel together.

JavaScript
const el = document.querySelector("p.animation");
const log = document.getElementById("log");
const btn = document.getElementById("toggle");
let iterations = 0;

function append(msg) {
  log.textContent += msg + " ";
}

el.addEventListener("animationstart", () => append("start"));
el.addEventListener("animationiteration", () => {
  iterations += 1;
  append("iteration:" + iterations);
});
el.addEventListener("animationend", () => {
  append("end");
  el.classList.remove("active");
  btn.textContent = "Activate animation";
});
el.addEventListener("animationcancel", () => append("canceled"));

btn.addEventListener("click", () => {
  el.classList.toggle("active");
  log.textContent = "";
  iterations = 0;
  const on = el.classList.contains("active");
  btn.textContent = on ? "Cancel animation" : "Activate animation";
});
Try It Yourself

How It Works

With animation-iteration-count: 2, you get one animationiteration between runs, then animationend after the last cycle. Canceling mid-run logs canceled instead.

🚀 Common Use Cases

  • Removing temporary entrance/exit animation classes after they finish.
  • Chaining UI steps: show the next panel only after the current animation ends.
  • Syncing analytics or sound cues with completed motion.
  • Teaching the CSS animation event set alongside animationstart and animationcancel.
  • Resetting buttons or loaders when a one-shot animation completes.

🔧 How It Works

1

CSS animation starts

animationstart fires; iterations may follow.

Play
2

Last iteration finishes

Duration and iteration-count are satisfied.

Complete
3

Browser fires animationend

An AnimationEvent is dispatched.

Event
4

Your handler cleans up

Remove classes, update UI, or start the next step.

📝 Notes

  • MDN: Baseline Widely available (since December 2019).
  • Not Deprecated, Experimental, or Non-standard — no status banner required.
  • Aborted animations do not fire animationend; pair with animationcancel when needed.
  • Infinite animations never fire animationend while they keep looping.
  • Related learning: animationcancel, addEventListener(), animate(), JavaScript hub.

Universal Browser Support

animationend is marked Baseline Widely available on MDN (since December 2019). Logos use the shared browser-image-sprite.png sprite from this project. Support for the companion animationcancel event is more limited—see that tutorial for details.

Baseline · Widely available

Element animationend

Works across modern desktop and mobile browsers for completed CSS animations.

100% Widely available
Google Chrome Supported · Desktop & Android
Full support
Mozilla Firefox Supported · Desktop & Android
Full support
Apple Safari Supported · macOS & iOS
Full support
Microsoft Edge Supported · Chromium
Full support
Opera Supported · Modern versions
Full support
Internet Explorer Legacy support with prefixes in older IE
Partial
animationend Baseline

Bottom line: Safe to use for cleanup after CSS animations complete. Also listen for animationcancel when interruptions matter.

Conclusion

animationend is the reliable “animation finished” signal for CSS Animations. Listen with addEventListener, read AnimationEvent details when you need them, and remember aborted animations take the animationcancel path instead.

Continue with animationiteration, addEventListener(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Prefer addEventListener("animationend", ...)
  • Remove one-shot animation classes inside the handler
  • Check event.animationName when multiple animations share a node
  • Also handle animationcancel for interrupt cleanup
  • Use finite animation-iteration-count when you need an end event

❌ Don’t

  • Expect animationend from infinite looping animations
  • Assume abort paths still fire animationend
  • Confuse with Web Animations API finish events
  • Forget animationiteration is separate from the final end
  • Leave animating classes on forever if you need to replay them

Key Takeaways

Knowledge Unlocked

Five things to remember about animationend

CSS animation completed—cleanup and chain the next step.

5
Core concepts
🎬 02

AnimationEvent

name + time

API
🚫 03

No abort fire

use cancel

Rule
🔔 04

addEventListener

preferred

Listen
🎯 05

Baseline

widely available

Compat

❓ Frequently Asked Questions

It fires when a CSS Animation has completed its intended run (including after the last iteration). If the animation aborts early — for example the element is removed from the DOM or the animation is removed from the element — animationend is not fired.
No. MDN marks Element animationend as Baseline Widely available (since December 2019). It is not Deprecated, Experimental, or Non-standard.
An AnimationEvent. Useful read-only properties include animationName, elapsedTime, and pseudoElement.
Use element.addEventListener("animationend", handler) or set element.onanimationend = handler. Prefer addEventListener when you need multiple handlers or easy removal.
animationend means the animation finished normally. animationcancel means it was aborted early (for example display: none or removing animation-name) and never reached a normal end.
No. Each completed iteration (except the last) fires animationiteration. After the final iteration finishes, animationend fires once.
Did you know?

If several CSS animations run on the same element, each one can fire its own animationend. Filter with event.animationName so you only react to the animation you care about.

Next: animationiteration

Learn when each CSS animation loop ends and the next begins.

animationiteration →

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