How to detect the end of CSS transition events in JavaScript

Before CSS transition and animation (keyframes), in order to animate, we need to code in JavaScript. However, once the CSS transition and animation properties were introduced, it made it so we can only achieve complex animations with CSS.

In JavaScript, we can call the callback function once the animation is done. But in CSS, there is no option to perform any action after the end of the transition/animation.

Whenever the transition is finished, the transitionend event will be triggered. We can use this event to find the end of the transition. We can also use it like ontransitionend.

If the browser is WebKit-based, then we need to define the prefix for the event.

"transition"      : "transitionend",
"OTransition"     : "oTransitionEnd", // opera
"MozTransition"   : "transitionend", // mozilla
"WebkitTransition": "webkitTransitionEnd"

Let’s create a practical example to detect the end of a transition.

First, we are going to create a search box that will expand when we focus on the input.

HTML: Create an Input Box

<input type="text" placeholder = "Enter the text">

CSS: Add Style to the Input Box

.search {
  width : 200px;
  height :30px;
  border :5px solid red;
  border-radius : 10px;
  padding : 10px;
  color : blue;
  outline:none;
  transition : all .3s linear;
}

Once the input box is focused, we need to increase its width.

.expand {
  width : 50vw;
}

JavaScript: Add focus and focusout listeners

let input = document.querySelector('.search');
input.addEventListener('focus',  function(ev, data) {
  input.classList.add('expand');
});
input.addEventListener('focusout',  function(ev, data) {
  input.classList.remove('expand');
});

Now, we need to detect the transition end event based on the browser. We can detect this by checking any of the transition events available in the style attribute of any element.

function getTransitionEndEventName() {
  var transitions = {
      "transition"      : "transitionend",
      "OTransition"     : "oTransitionEnd",
      "MozTransition"   : "transitionend",
      "WebkitTransition": "webkitTransitionEnd"
   }
  let bodyStyle = document.body.style;
  for(let transition in transitions) {
      if(bodyStyle[transition] != undefined) {
          return transitions[transition];
      } 
  }
}

// using above code we can get Transition end event name
let transitionEndEventName = getTransitionEndEventName();

Now, we need to add the event listener once the input is focused. For that, add the event listener inside the focus event callback.

input.addEventListener('focus',  function(ev) {
  input.classList.add('expand');
  input.addEventListener(transitionEndEventName, onTransitionEnd);
});

Once the transition is finished, the callback function will be called.

We also need to remove the transitioned event once the callback is executed; otherwise, the listener will keep running, which may cause it to run multiple times.

For example:

Upon focusing the input, the input box will expand (this is one transition). However, once the focus is out, the input box shrinks (this is another transition). So, on focusing, we will add an eventListener and then remove the transitionend event listener when the focus out. This way, the transitionend event will not be handled for focusout.

function onTransitionEnd(ev) {
    console.log("transition  finished ");
    input.removeEventListener(transitionEndEventName, callback);
}
Console
Attributions:
  1. undefined by undefined